<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Javier Toledo</title>
    <description>The latest articles on Forem by Javier Toledo (@javier_toledo).</description>
    <link>https://forem.com/javier_toledo</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F155931%2F9756a375-c543-4ad7-aca1-868ef94b9946.jpg</url>
      <title>Forem: Javier Toledo</title>
      <link>https://forem.com/javier_toledo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/javier_toledo"/>
    <language>en</language>
    <item>
      <title>Abstractions, Components, Services, and Libraries in Software Projects</title>
      <dc:creator>Javier Toledo</dc:creator>
      <pubDate>Thu, 31 Oct 2024 16:30:26 +0000</pubDate>
      <link>https://forem.com/javier_toledo/abstractions-components-services-and-libraries-in-software-projects-151m</link>
      <guid>https://forem.com/javier_toledo/abstractions-components-services-and-libraries-in-software-projects-151m</guid>
      <description>&lt;p&gt;In software projects, terms like abstractions, components, services, and libraries are often used in daily communication, and sometimes, it becomes confusing. They all describe reusable code, but each has specific connotations that help engineers communicate more effectively. Here's a brief overview of each.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. &lt;a href="https://en.wikipedia.org/wiki/Abstraction_(computer_science)" rel="noopener noreferrer"&gt;Abstractions&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Abstractions simplify complex systems by hiding unnecessary details and providing a simplified interface. For example, a data access layer abstracts database operations, allowing developers to work with higher-level concepts without dealing with SQL queries. This is a very broad term because any component, service, or library is indeed an abstraction, but we tend to use it to emphasize that we're hiding part of a problem's complexity.&lt;/p&gt;

&lt;p&gt;Using abstractions is essential in computer science because, otherwise, our only tool would be electrical signals coming and going through a cable. Zeroes and ones abstract us from remembering the correct voltage representing an activated or deactivated state in a transistor. Logic gates are abstractions of a bunch of transistors, processors are abstractions of logic gates, and this goes all the way up to data structures that map to real-world concepts (like an invoice) or windows drawn on a screen (which are indeed just code drawing colored dots here and there).&lt;/p&gt;

&lt;h2&gt;
  
  
  2. &lt;a href="https://en.wikipedia.org/wiki/Software_component" rel="noopener noreferrer"&gt;Components&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Components are modular, self-contained parts of a system that encapsulate specific functionality. They allow us to group the related code and better manage code responsibility (i.e., all the code related to managing tickets goes into the ticketing component). They are designed to be reusable and loosely coupled, meaning they interact with other components through well-defined interfaces. Component is still a generic term that can refer to almost any reusable piece of code. An example is a "user login form" in a web application or a set of functions that allow your software to make financial calculations.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. &lt;a href="https://en.wikipedia.org/wiki/Service_(systems_architecture)" rel="noopener noreferrer"&gt;Services&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Services are independent components that provide specific functionality, often over a network. They are commonly used in service-oriented or microservices architectures, such as a "payment processing service" that handles payments through APIs. A service's key distinction is that it runs independently from the main program as a separate program so that it can be developed separately. The way to use a service is through the operating system's standard functions (Like inter-process messaging, files, pipes, or network messages).&lt;/p&gt;

&lt;p&gt;Suppose you're developing an application that depends on a service. In that case, you'll need to start that service (Often a different app) before starting your application, and if you stop the service, your app will stop functioning. This is extremely useful when running your app on one computer and the service on another, which essentially enables the Internet. All websites are services running on someone's servers that the browser in our machine uses.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. &lt;a href="https://en.wikipedia.org/wiki/Library_(computing)" rel="noopener noreferrer"&gt;Libraries&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Libraries are collections of reusable code that provide specific functionality to be embedded in your program, such as a "date manipulation library." Unlike services, libraries are distributed as part of the application code in the same program, so they cannot run independently on different machines. In other words, when we use libraries, they become part of our code in the final executable.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Dynamic_linker" rel="noopener noreferrer"&gt;Dynamic libraries&lt;/a&gt; are a feature of modern operating systems that prevent common libraries from being duplicated in all programs. Because these libraries are often distributed independently, they can be confused with services, but they behave as if they were embedded in your app without any communication mechanism. The operating system dynamically links them when your app starts. When a program doesn't use dynamic libraries, we say it's a statically linked binary and has the advantage of being runnable anywhere without installing any dependencies.&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Abstractions&lt;/strong&gt; simplify systems by hiding details.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Components&lt;/strong&gt; are reusable parts of a larger system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Services&lt;/strong&gt; provide functionality independently, often distributed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Libraries&lt;/strong&gt; are reusable code collections embedded in applications.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Libraries and services can be considered components of a larger system, as they encapsulate specific functionality and enhance the overall system architecture. Furthermore, all these concepts are ultimately abstractions, as they simplify complex functionality and make it easier for developers to work with software systems. These terms are important because they help us discuss how to reuse our code or use third-party code when creating new software.&lt;/p&gt;

</description>
      <category>abstractions</category>
      <category>architecture</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Will AIs Replace Software Systems As We Know Them?</title>
      <dc:creator>Javier Toledo</dc:creator>
      <pubDate>Fri, 02 Jun 2023 21:29:07 +0000</pubDate>
      <link>https://forem.com/javier_toledo/will-ais-replace-software-systems-as-we-know-them-58m8</link>
      <guid>https://forem.com/javier_toledo/will-ais-replace-software-systems-as-we-know-them-58m8</guid>
      <description>&lt;p&gt;Machine learning models draw much of their inspiration from biological brains. Composed of millions of neurons working in unison, these models are extremely powerful. However, like biological intelligence, they are susceptible to occasional errors or confusion. By structuring data, enriching it with metadata, or setting guardrails on the way it's processed, we can significantly enhance their accuracy. This improvement is feasible because we're enhancing a system with excellent computational abilities and superior memory (traditional computers) with robust machine learning models capable of solving problems that cannot be easily described with mathematical formulas or code.&lt;/p&gt;

&lt;p&gt;This scenario arises because AI and traditional computing are based on fundamentally different computing models. AI exhibits the capability for "Fuzzy Logic", which relates to understanding problems with imprecise inputs and outputs, such as recognizing a human face in various positions or transcribing sound from a noisy recording. In contrast, traditional computers operate on "Exact Logic", in which both the inputs and outputs can be described with high precision, and any variation must be explicitly encoded. Examples of such operations include performing mathematical computations or removing all uppercase letters from a paragraph.&lt;/p&gt;

&lt;p&gt;Consequently, when AI models and traditional computers collaborate, their combined effectiveness significantly increases. Leveraging their individual strengths, they form a synergy analogous to our relation with the applications we use every day. The apps on our mobile phones and computers give us almost superhuman abilities, like perfect and virtually limitless memory, the potential to visualize and act on unusual health data, or even talk in real-time with someone on the other side of the globe. Unlike us, AI applications don't require user interfaces as they can swiftly process and operate on raw data. However, they can use APIs and databases, in the same way we use apps and notepads.&lt;/p&gt;

&lt;p&gt;In my view, AI is not here to replace traditional software. Instead, it brings it to a new level by giving us tools to introduce features that were unthinkable just a year ago. AI will empower us to build more intelligent machines with impeccable memory that can interact with humans in more natural ways while retaining existing computer capabilities. &lt;/p&gt;

&lt;p&gt;So software will likely remain the same under the hoods, but the ways we interact with computers will likely change radically. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We can now create machines that can talk.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>softwareengineering</category>
      <category>llm</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Don't waste time building another API, let the machines make them for you with the Booster Framework!</title>
      <dc:creator>Javier Toledo</dc:creator>
      <pubDate>Tue, 11 May 2021 17:37:35 +0000</pubDate>
      <link>https://forem.com/boostercloud/don-t-waste-time-building-another-api-let-the-machines-make-them-for-you-with-the-booster-framework-4d2c</link>
      <guid>https://forem.com/boostercloud/don-t-waste-time-building-another-api-let-the-machines-make-them-for-you-with-the-booster-framework-4d2c</guid>
      <description>&lt;p&gt;Building a great API is not trivial, you have to design the data structure, choose the right connection mechanism, implement handlers for every endpoint, serialize/deserialize the data and validate it before accepting it in your business logic.&lt;/p&gt;

&lt;p&gt;In addition to that, it is often necessary to build API clients for front-end applications or for other services in order to make use of the functionality offered by your service.&lt;/p&gt;

&lt;p&gt;If you use &lt;a href="https://graphql.org/"&gt;GraphQL&lt;/a&gt;, the second part can definitely be simplified, as you can use any &lt;a href="https://github.com/apollographql/apollo-client"&gt;standard GraphQL client&lt;/a&gt; to query the system, but &lt;a href="https://blog.logrocket.com/why-you-shouldnt-use-graphql/"&gt;manually building and maintaining schemas and resolvers is still such a hassle that some teams might prefer to stay in REST&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Boost your API with CQRS!
&lt;/h1&gt;

&lt;p&gt;The Booster Framework introduces a very different approach to building APIs: &lt;strong&gt;not doing it at all!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is only possible thanks to the opinionated implementation of &lt;a href="https://www.martinfowler.com/bliki/CQRS.html"&gt;the CQRS pattern&lt;/a&gt; and Booster's inference capabilities. Let's walk through &lt;a href="https://docs.booster.cloud/#/chapters/03_booster-architecture"&gt;the structure of a typical Booster application&lt;/a&gt; before going back to APIs.&lt;/p&gt;

&lt;p&gt;In a Booster application, most functionality is defined in commands. A &lt;a href="https://docs.booster.cloud/#/chapters/03_booster-architecture?id=_1-command-and-command-handlers"&gt;&lt;code&gt;Command&lt;/code&gt;&lt;/a&gt; is a data structure that has a handler, like this one that processes a backflip:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;authorize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;all&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;PerformABackflip&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;personName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;personAge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PerformABackflip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;register&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Register&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;luck&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;personAge&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;35&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;luck&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;register&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PersonSurvivedABackflip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;personName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;callAnAmbulance&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="nx"&gt;register&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AmbulanceCalled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;personName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a command handler is processed, it finishes by writing one or more events into the event store. In this case, a &lt;code&gt;PersonSurvivedABackflip&lt;/code&gt; event for lucky or young people, or an &lt;code&gt;AmbulanceCalled&lt;/code&gt; for the rest of us 😅.&lt;/p&gt;

&lt;p&gt;An &lt;a href="https://docs.booster.cloud/#/chapters/03_booster-architecture?id=_2-events"&gt;&lt;code&gt;Event&lt;/code&gt;&lt;/a&gt; is just a data structure that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Event&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;PersonSurvivedBackflip&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;personName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="cm"&gt;/* We define the `entityID` method to help Booster match 
  the event with the corresponding entity */&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;entityID&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;personName&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These events are later &lt;a href="https://docs.booster.cloud/#/chapters/03_booster-architecture?id=_4-entities-and-reducers"&gt;reduced into entities&lt;/a&gt; that represent the current state. The reduction is carried out by reducer functions that look like these:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Entity&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;backflipTrials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;backflipSuccesses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Reduces&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PersonSurvivedBackflip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;reduceSurvival&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PersonSurvivedBackflip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="nx"&gt;currentPerson&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;
  &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;buildNextPersonObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentPerson&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Reduces&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AmbulanceCalled&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;reduceFailure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AmbulanceCalled&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;currentPerson&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;buildNextPersonObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentPerson&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;buildNextPersonObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;currentPerson&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;trials&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentPerson&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;backflipTrials&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;successes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentPerson&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;backflipSuccesses&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;successes&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;personName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;trials&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;successes&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Securing queries with Read Models
&lt;/h1&gt;

&lt;p&gt;At this point, the CQRS design helped us to separate the data schema that the system accepts (commands) from the state data schema (entities). This in itself already simplifies the API design: The API schema could just match the command and entity schemas, and we could call that a nice API. But before calling it a day, we need to make an extra consideration; Allowing direct API access to entities would mean no restrictions on data access, so private fields like password hashes or bank accounts would become accessible. That's why Booster adds Read Models to the mix.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.booster.cloud/#/chapters/03_booster-architecture?id=_5-read-models-and-projections"&gt;&lt;code&gt;ReadModels&lt;/code&gt;&lt;/a&gt; are eventual consistent caches of the internal state. They're not only a way to filter which fields you want to make accessible, but they can also aggregate related data or make small data transformations to optimize reads. Accessing read models is highly performant and they're updated in real-time when data changes, pushing these changes to the client applications. &lt;/p&gt;

&lt;p&gt;A typical read model that projects a single entity would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;ReadModel&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;authorize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;all&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;PersonReadModel&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;backflipTrials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;backflipSuccesses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Projects&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;projectPerson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;currentState&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;PersonReadModel&lt;/span&gt;
  &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;ProjectionResult&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PersonReadModel&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;PersonReadModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="nx"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;backflipTrials&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;backflipSuccesses&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Inferring APIs from code!
&lt;/h1&gt;

&lt;p&gt;At this point, we could build a very nice, useful, and secure API by just copying the schemas from the classes decorated as &lt;code&gt;Command&lt;/code&gt; or &lt;code&gt;ReadModel&lt;/code&gt;, and &lt;a href="https://docs.booster.cloud/#/chapters/04_features?id=graphql-api"&gt;that's exactly what Booster does for you&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Booster analyzes the class structure of all classes decorated as &lt;code&gt;@Command&lt;/code&gt; or &lt;code&gt;@ReadModel&lt;/code&gt; in compile-time, generating metadata that is used in deploy time to &lt;a href="https://docs.booster.cloud/#/chapters/02_getting-started?id=_6-deployment"&gt;generate a GraphQL schema and provision all the cloud resources required to make the application work&lt;/a&gt;, including API gateways, lambda functions, containers, permissions, and even the database tables to store the events.&lt;/p&gt;

&lt;p&gt;For some people, this might look similar to maintaining the schema in a regular GraphQL schema file, because, at the end of the day, you're still expressing the schemas as &lt;code&gt;Command&lt;/code&gt; and &lt;code&gt;ReadModel&lt;/code&gt; classes, but Booster brings many extra advantages to the table:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Commands, Read Models, and all their usages are &lt;strong&gt;type-checked in compile-time&lt;/strong&gt;, reducing or eliminating the likelihood of making mistakes.&lt;/li&gt;
&lt;li&gt;No errors can be introduced when serializing/deserializing data because this is &lt;strong&gt;done transparently&lt;/strong&gt; by the framework.&lt;/li&gt;
&lt;li&gt;When you update a command or a read model, &lt;strong&gt;the API is updated automatically&lt;/strong&gt;, you don't need to change any other files.&lt;/li&gt;
&lt;li&gt;Resolvers are hidden under &lt;strong&gt;higher-level abstractions&lt;/strong&gt; like commands or read models, so you don't need to deal with low-level protocol nuances.&lt;/li&gt;
&lt;li&gt;All Read Models &lt;strong&gt;support WebSockets by default&lt;/strong&gt;, so there is no need to implement any extras for real-time support in your applications.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To summarize, by writing highly semantic code and letting the machine do the heavy lifting, &lt;a href="https://booster.cloud"&gt;Booster&lt;/a&gt; allows you to build fully functioning real-time APIs in a breeze, making everything else work out of the box, and saving a ton of time that you can use to add new use cases, write better tests, or manage elusive corner cases.&lt;/p&gt;

&lt;h1&gt;
  
  
  Try it!
&lt;/h1&gt;

&lt;p&gt;Booster is a 100% open-source project developed by &lt;a href="https://www.theagilemonkeys.com"&gt;The Agile Monkeys&lt;/a&gt;. You can &lt;a href="https://docs.booster.cloud/#/chapters/02_getting-started?id=installing-booster"&gt;get its full potential for free and with no hidden fees&lt;/a&gt;. The typical Booster application can be run on the free tier in &lt;a href="https://aws.amazon.com/"&gt;AWS&lt;/a&gt;, but it also has experimental support for &lt;a href="https://azure.microsoft.com/en-us/"&gt;Azure&lt;/a&gt; and &lt;a href="https://kubernetes.io/"&gt;Kubernetes&lt;/a&gt;, so you can run it locally using &lt;a href="https://minikube.sigs.k8s.io/docs/"&gt;Minikube&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Learn more about Booster on &lt;a href="https://booster.cloud"&gt;the official website&lt;/a&gt;, &lt;a href="https://docs.booster.cloud/#/"&gt;the documentation&lt;/a&gt;, or &lt;a href="https://github.com/boostercloud/booster"&gt;the Github project&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you try it out, be sure to let us know what you thought of it on &lt;a href="https://discord.gg/bDY8MKx"&gt;the project’s Discord channel&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>api</category>
      <category>graphql</category>
      <category>productivity</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Playing with promises and concurrency in TypeScript</title>
      <dc:creator>Javier Toledo</dc:creator>
      <pubDate>Tue, 24 Nov 2020 22:17:48 +0000</pubDate>
      <link>https://forem.com/javier_toledo/playing-with-promises-and-concurrency-in-typescript-54ii</link>
      <guid>https://forem.com/javier_toledo/playing-with-promises-and-concurrency-in-typescript-54ii</guid>
      <description>&lt;p&gt;I still remember how hard it was to understand promises the first time I learned them. Modern languages have built constructs like JavaScript's async/await to make it easier to synchronize processes and keep things simple. With async/await, you can write asynchronous code as if it was synchronous, but as with any abstraction, understanding the underlying mechanisms will help you to understand what's going on when things start behaving in unexpected ways.&lt;/p&gt;

&lt;p&gt;We recently found an issue that drove our entire team nuts for a couple of hours. We deployed a lambda function to AWS that performed several tasks concurrently. To do that, we wrote code that looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;task1&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{...}&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;task2&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{...}&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;task3&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{...}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;doAllTheThings&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;task1&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nx"&gt;task2&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nx"&gt;task3&lt;/span&gt;&lt;span class="p"&gt;()])&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This worked nicely... until one of the tasks failed. When that happens, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all"&gt;&lt;code&gt;Promise.all&lt;/code&gt;&lt;/a&gt; is automatically rejected, and the &lt;code&gt;doAllTheThings&lt;/code&gt; method stops "awaiting", no matter what's the state of the other tasks. In our case, it looks like once the lambda returned the error response, it was killed, canceling the remaining ongoing tasks without notice. There's a shiny new &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled"&gt;&lt;code&gt;Promise.allSettled&lt;/code&gt;&lt;/a&gt; method introduced in Node 12.9 that waits for all promises to either be fulfilled or rejected before emitting a response, but it's not available if you're not targeting ES2020 (which is our case). Discussing ideas to solve this without using the new &lt;code&gt;Promise.allSettled&lt;/code&gt; method, we realized that the team had different levels of understanding of what was actually going on under the hoods, so... time for a back-to-basics article!&lt;/p&gt;

&lt;h2&gt;
  
  
  What is actually a promise?
&lt;/h2&gt;

&lt;p&gt;Starting from the beginning, a Promise is not black magic sorcery, it's just an object that is smartly designed to hide the complexities of dealing with asynchronous code. You can even create your own custom promise objects if you want. This is a simple promise implementation to help you understand the basics:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;MyOwnPromise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TValue&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cm"&gt;/* The promise holds the value, which is initially "unknown", meaning
     * that the promise is "pending". Once this value is set, 
     * we say that the promise is "resolved". The error will also be "cached" */&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;TValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;

    &lt;span class="c1"&gt;// Callbacks set before fulfillment are put in these queues&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="na"&gt;thenQueue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="na"&gt;catchQueue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="cm"&gt;/* The constructor gets an `execFunction` with the user's code.
     * This function is asynchronous and calls the `resolveCallback` when the process
     * is fulfilled or the `rejectCallback` function when it isn't. */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="na"&gt;execFunction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="na"&gt;resolveCallback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
            &lt;span class="na"&gt;rejectCallback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="cm"&gt;/* The user's `execFunction` is called in the constructor, this is important
         * to understand that any promise you create starts running right away, 
         * no matter if you await for it or not */&lt;/span&gt;
        &lt;span class="nx"&gt;execFunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="cm"&gt;/* When the user calls to the `resolveCallback`, we save the value
                 * and call the `then` callbacks to notify the user about the
                 * resolved value */&lt;/span&gt;
                &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;
                &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;thenCallback&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;thenQueue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nx"&gt;thenCallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="cm"&gt;/* When the user calls to the `rejectCallback` with an error,
                 * we cache the error and call the `catch` callbacks in the queue. */&lt;/span&gt;
                &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;
                &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;catchCallback&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;catchQueue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nx"&gt;catchCallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cm"&gt;/* The user calls to `then` to receive a callback when the promise
     * is resolved. */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="cm"&gt;/* When the promise is resolved, the callback is called right away.
             * This is important, and means that the user don't need to know 
             * if a promise is fulfilled or not before registering their callback.*/&lt;/span&gt;
            &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// When is pending, we append the callback to the queue&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;thenQueue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="cm"&gt;/* In the same way, when there's an error, we just send it to 
             * the callback right away. */&lt;/span&gt;
            &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="cm"&gt;/* When there are no errors, we append the callback to the queue */&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;catchQueue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using this code as a reference, we can see that the most important properties of the promises that are important to remember:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They encapsulate asynchronous code, but they are not processes.&lt;/li&gt;
&lt;li&gt;The asynchronous code is started right away no matter if the promise is awaited or not.&lt;/li&gt;
&lt;li&gt;Promises smartly cache their values and errors, so the user doesn't need to know the internal state of the promise to deal with it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What do async/await actually do?
&lt;/h2&gt;

&lt;p&gt;Okay, this might sound like it has nothing to do with async/await, so let's see first how our &lt;code&gt;MyOwnPromise&lt;/code&gt; is used. Let's say I want to "promisify" a task that takes some time and can fail with an exception. I can do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// I create my promise, my code will be started right away&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myOwnPromise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;MyOwnPromise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;longRunningTask&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// If I want to receive the value once the process is completed:&lt;/span&gt;
&lt;span class="nx"&gt;myOwnPromise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;My value is &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;// To log the errors:&lt;/span&gt;
&lt;span class="nx"&gt;myOwnPromise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Ooops: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Async functions and the await keyword were introduced in ECMAScript 2017. The &lt;code&gt;async&lt;/code&gt; keyword transforms a function into a "promise builder". It forces a function to return a promise that is fulfilled with any value it returns or rejected with any exception raised. This means that we can rewrite our previous code like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// I just need to wrap my `longRunningTask` in an async function to build my promise. I can do this only because my task runs synchronously. If it was asynchronous, I'd need to wrap it in a new promise object anyway.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myOwnPromise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;longRunningTask&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;})()&lt;/span&gt;

&lt;span class="c1"&gt;// Everything else works in the same way because the returned object is a promise&lt;/span&gt;
&lt;span class="nx"&gt;myOwnPromise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;My value is &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nx"&gt;myOwnPromise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Ooops: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;await&lt;/code&gt; keyword waits for a promise to be fulfilled and unwraps its value. If the promise is rejected, it throws the error as an exception. So we can finally rewrite our code like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myOwnPromise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;longRunningTask&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;})()&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// I just need to "await" for it:&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;myOwnPromise&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;My value is &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Ooops: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So async/await basically makes async code feel like it's synchronous code, but the most important thing to remember at this point is that all the versions of the code in this section are equivalent, &lt;code&gt;async&lt;/code&gt; and &lt;code&gt;await&lt;/code&gt; are just convenient &lt;strong&gt;syntactic sugar&lt;/strong&gt; to help us reason about our asynchronous code, but the promise objects are still being created under the hoods in the same way. Promises are run when they're created, and we can play a bit with the awaits to achieve different execution schemes:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Running a sequence of tasks:
&lt;/h3&gt;

&lt;p&gt;This is the easy scenario. Awaiting the promises as they are created we can block them from running until the previous one is completed. You often do this when one task require previous tasks results:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;task1&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;task2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;task3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Running the tasks concurrently placing the awaits strategically
&lt;/h3&gt;

&lt;p&gt;If you create all the tasks without immediately awaiting for them, they'll run concurrently, but managing errors could be tricky. In this case, all tasks will run concurrently, but if, let's say, &lt;code&gt;task2&lt;/code&gt; fails, it will wait for &lt;code&gt;task1&lt;/code&gt; to finish before raising the exception.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;promise1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;task1&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;promise2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;task2&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;promise3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;task3&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;promise1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;promise2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// If this one fails, we won't notice until `promise1` is fulfilled&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;promise3&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Running tasks concurrently wrapping them in another promise!
&lt;/h3&gt;

&lt;p&gt;Once you understand how promises, &lt;code&gt;async&lt;/code&gt; and &lt;code&gt;await&lt;/code&gt; work, you can combine them to achieve advanced behaviors. For instance, we could emulate what &lt;code&gt;Promise.all&lt;/code&gt; do wrapping the whole process in a new promise that is only resolved when all the promises have been resolved and rejected immediately on the first rejection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;customPromiseAll&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;promises&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// We initialize an `fulfilled` boolean array of the size of `promises`&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pending&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;promises&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;promises&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;promise&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="c1"&gt;// When a promise is resolved, we store this fact in our array&lt;/span&gt;
                    &lt;span class="nx"&gt;pending&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
                    &lt;span class="c1"&gt;// If there are no pending promises, we can resolve our main promise&lt;/span&gt;
                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;pending&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;isPending&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;isPending&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;})&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Any failure in one of the promises will make the main promise rejected&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And back to our original problem: Making sure that we properly wait for all our promises to be settled (resolved or rejected). We can implement our own version of &lt;code&gt;Promise.allSettled&lt;/code&gt; like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;PromiseResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pending&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fulfilled&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rejected&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;customPromiseAllSettled&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;promises&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PromiseResult&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// We initialize a `results` array of the size of `promises`&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PromiseResult&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;promises&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pending&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;resolveIfNothingPending&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// If there are no pending promises, we can resolve our main promise&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pending&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; 

        &lt;span class="nx"&gt;promises&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;promise&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="c1"&gt;// When a promise is resolved, we store the value and status&lt;/span&gt;
                    &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fulfilled&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; 
                    &lt;span class="nx"&gt;resolveIfNothingPending&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="p"&gt;})&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="c1"&gt;// When there's an error, we store it in the `results` array too&lt;/span&gt;
                    &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rejected&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
                    &lt;span class="nx"&gt;resolveIfNothingPending&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="p"&gt;})&lt;/span&gt; 
        &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;In this article, we've gone through the internals of promises, this little, but powerful object that significantly simplifies how you deal with asynchronous code. We've seen how there's little magic in this truly magical object, and how you can use promises, &lt;code&gt;async&lt;/code&gt; and &lt;code&gt;await&lt;/code&gt; to build complex behaviors. In a production project, I wouldn't recommend implementing your own promise classes or combinator functions if you can use functions like &lt;code&gt;Promise.allSettled&lt;/code&gt;, but understanding promises well is definitely an ace up your sleeve in your developer tool kit. I hope you liked it!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;small&gt;Cover photo by &lt;a href="https://unsplash.com/@gitfo?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Gerrie van der Walt&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/industrial?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;*&lt;small&gt;&lt;em&gt;Disclaimer: I edited the code samples in VSCode to make sure the syntax is correct, but haven't run them in real scenarios. If a code snippet doesn't work, let me know in the comments, I'll be happy to fix it!&lt;/em&gt;&lt;/small&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>concurrency</category>
      <category>promises</category>
    </item>
    <item>
      <title>Currying in TypeScript (just for fun)</title>
      <dc:creator>Javier Toledo</dc:creator>
      <pubDate>Tue, 23 Jun 2020 10:30:35 +0000</pubDate>
      <link>https://forem.com/theagilemonkeys/currying-in-typescript-just-for-fun-5h9</link>
      <guid>https://forem.com/theagilemonkeys/currying-in-typescript-just-for-fun-5h9</guid>
      <description>&lt;p&gt;Let's have some fun with TypeScript syntax. Thanks to the fat arrow interface, you can easily match (with some caveats) one of the best features of Haskell called &lt;a href="https://wiki.haskell.org/Currying"&gt;currying&lt;/a&gt;. Currying is the ability to partially apply a function. Let's build a small function that concats strings first, we'll see a situation on which this technique can be useful.&lt;/p&gt;

&lt;p&gt;An obvious reference implementation for our cat function could be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But this function can't be applied partially if we call it with just the first parameter, we'll have a funny result (thanks JavaScript):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello undefined&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Haskell all functions are curried by default, so the obvious implementation will behave very differently:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
&lt;span class="n"&gt;cat&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="s"&gt;" "&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;

&lt;span class="c1"&gt;-- Calling it with one parameter returns a &lt;/span&gt;
&lt;span class="c1"&gt;-- partially applied function&lt;/span&gt;
&lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;catHello&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cat&lt;/span&gt; &lt;span class="s"&gt;"hello"&lt;/span&gt; 

&lt;span class="c1"&gt;-- we can apply the other parameter later&lt;/span&gt;
&lt;span class="n"&gt;catHello&lt;/span&gt; &lt;span class="s"&gt;"World"&lt;/span&gt; 
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Hello World"&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fat arrow syntax and TypeScript type annotations allow us to implement currying in a &lt;del&gt;non really that&lt;/del&gt; surprisingly similar way. The trick is very easy, we just need to nest single-parameter functions that return a function for the next parameter, writing the implementation in the last function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;

&lt;span class="c1"&gt;// To apply the whole function, you'd need to pass &lt;/span&gt;
&lt;span class="c1"&gt;// the parameters separately:&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;World&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello World&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;catHello&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;catHello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;World&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello World&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;If you're wondering how this can possibly work: A function defined in another function can access the scope of the previous function via closures, so inner functions can see the parameter values of previous ones. You can &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures"&gt;learn more about this useful technique here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Notice that if we could remove the parentheses, the implementation would be almost the same as Haskell's!&lt;/p&gt;

&lt;h3&gt;
  
  
  Why partial application is interesting?
&lt;/h3&gt;

&lt;p&gt;It is a nice way to inject context or dependencies into functions without wrapping them in classes, and they're an awesome tool combined with iterators or to build callbacks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;dbWrite&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dbConnection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DBConnection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dbConnection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;productionDBWrite&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dbWrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;productionDBConnection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;productionDBWrite&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  BUT... you probably want to use &lt;code&gt;bind&lt;/code&gt; instead!
&lt;/h1&gt;

&lt;p&gt;As I said at the beginning of the article, I wrote it just for fun, I love to find how languages like Haskell inspire features and new ways of thinking in other more trendy languages.&lt;/p&gt;

&lt;p&gt;In JavaScript you can use &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind"&gt;&lt;code&gt;Function.prototype.bind()&lt;/code&gt;&lt;/a&gt; to achieve similar results:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;catHello&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="c1"&gt;// Take into account that the first parameter defines &lt;/span&gt;
&lt;span class="c1"&gt;// where "this" points to in the bound function. It's &lt;/span&gt;
&lt;span class="c1"&gt;// important to remember this if you're building a &lt;/span&gt;
&lt;span class="c1"&gt;// bound function from a class method. As we don't &lt;/span&gt;
&lt;span class="c1"&gt;// reference `this` in our function, it's fine to just &lt;/span&gt;
&lt;span class="c1"&gt;// pass `null` here.&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;catHello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;World&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello World&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We use this technique extensively in &lt;a href="https://booster.cloud"&gt;Booster Framework&lt;/a&gt; to reduce code complexity. Feel free to &lt;a href="https://spectrum.chat/boostercloud?tab=posts"&gt;join our community&lt;/a&gt; and practice some hardcore TypeScript techniques there, contributions from any skill level are highly appreciated, there's nothing like learning together!&lt;/p&gt;

</description>
      <category>currying</category>
      <category>haskell</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Become a better software engineer by opening yourself to different viewpoints</title>
      <dc:creator>Javier Toledo</dc:creator>
      <pubDate>Sat, 07 Mar 2020 22:29:13 +0000</pubDate>
      <link>https://forem.com/theagilemonkeys/become-a-better-software-engineer-by-opening-yourself-to-different-viewpoints-50p3</link>
      <guid>https://forem.com/theagilemonkeys/become-a-better-software-engineer-by-opening-yourself-to-different-viewpoints-50p3</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;a href="https://www.linkedin.com/pulse/become-better-software-engineer-opening-yourself-different-toledo/"&gt;Originally posted in Linkedin&lt;/a&gt;&lt;/em&gt;. Photo by &lt;a href="https://unsplash.com/@worthyofelegance"&gt;Alex on Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  The &lt;strong&gt;natural human tendency toward polarization&lt;/strong&gt; and the &lt;strong&gt;lack of reliable scientific data&lt;/strong&gt; about methodologies, technical procedures, and tools can &lt;strong&gt;result in never-ending discussions and poor technical decisions&lt;/strong&gt;.
&lt;/h3&gt;

&lt;p&gt;If you're a software engineer, you’ve probably found yourself in one of those discussions that drive us all nuts. The debate could be over functional programming versus procedural, shared state versus stateless, tabs vs spaces, or whether you're doing TDD, or Scrum, or doing  “the right way.™”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We all love passionate discussions about technology&lt;/strong&gt;, and it's easy to argue in favor or against any of those topics with pros and cons. But &lt;strong&gt;the way we weight our arguments is rarely based on evidence&lt;/strong&gt;—it’s often &lt;strong&gt;purely based on our own personal experiences or marvelous tales&lt;/strong&gt; told by people or brands that we admire (“It was invented to solve the huge challenges in Facebook, so it should work for us too!” – we all said a few months before it ruined the entire web.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Our opinions are very often not based on science&lt;/strong&gt;. Nobody has run a serious study to measure how much a solid Haskell type system reduces the bug count compared to the lousy dynamic nature of Ruby (Disclaimer: I &lt;strong&gt;love&lt;/strong&gt; both of those languages—this was just an example!), but we still love to argue about it anyway. &lt;strong&gt;Our opinions on those matters come basically from&lt;/strong&gt; &lt;a href="https://en.wikipedia.org/wiki/Confirmation_bias"&gt; confirmation bias&lt;/a&gt;, the inherent tendency of all humans to &lt;strong&gt;interpret information in a way that strengthens their own convictions&lt;/strong&gt;. This means that what you believe is likely influenced strongly by who your mentors were, what books you have read, and who you talk about tech with.&lt;/p&gt;

&lt;p&gt;To make things worse, most of us usually hang out with groups that think alike, &lt;strong&gt;reinforcing our thoughts&lt;/strong&gt; even more and &lt;strong&gt;making us tend to look for radical silver-bullet ideas&lt;/strong&gt;: “If you don't do TDD correctly, you're not a developer”; “If you don't follow every point in scrum, you're not professional”; “If you still use classes, you're a dinosaur”; “We ALWAYS do this, so NEVER do it differently.”&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The rate of “nevers” and “always” in a conversation about code could work as a perfect indicator of upcoming bad decisions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This tendency is a well-studied social psychology phenomenon called &lt;a href="https://en.wikipedia.org/wiki/Group_polarization"&gt; group polarization&lt;/a&gt;, and, guess what: &lt;strong&gt;it's not doing anyone any favors&lt;/strong&gt;. It makes us use the same tools or procedures for every situation, even when they are not applicable or it’s not the most practical approach. Being polarized and having &lt;strong&gt;extreme views on any topic in programming makes you a worse engineer&lt;/strong&gt;, not a better one, but tragically, &lt;strong&gt;extremism is often confused with wisdom&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://en.wikipedia.org/wiki/Software_engineering"&gt;Wikipedia page on software engineering&lt;/a&gt; reads /"Software engineering is the systematic application of &lt;strong&gt;engineering approaches&lt;/strong&gt; to the development of software." The &lt;a href="https://en.wikipedia.org/wiki/Engineering"&gt;engineering page&lt;/a&gt; defines engineering as "the use of &lt;strong&gt;scientific principles&lt;/strong&gt; to design and build machines, structures, and other items..."&lt;/p&gt;

&lt;p&gt;So, &lt;strong&gt;where's the science in our day-to-day decisions?&lt;/strong&gt; Are we really making decisions based on evidence, or is it just a mix of personal choices reinforced by the people around us? &lt;/p&gt;

&lt;p&gt;The truth is that &lt;strong&gt;nothing is black or white&lt;/strong&gt; in programming because &lt;strong&gt;programming is complex&lt;/strong&gt; and &lt;strong&gt;we’re all learning as we go&lt;/strong&gt;. Most approaches, techniques, and technologies &lt;strong&gt;were created to solve a specific problem&lt;/strong&gt;, or try to solve it in a better way. Take a look at any specific tool, and you’ll find that it was created to be the perfect tool to solve a particular problem under a particular set of conditions. Otherwise it wouldn't exist! &lt;strong&gt;But we cannot drive our decisions based on what we like or what we hate&lt;/strong&gt;. We have to &lt;strong&gt;fight our natural biases&lt;/strong&gt; and understand the real pros and cons of the tools and methodologies we use, especially the context (budget, team knowledge, disposability of the software, etc.), if we want to keep evolving as programmers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hate or rejection never helped anyone&lt;/strong&gt;: they’re usually just an indicator of what you don’t understand. &lt;strong&gt;Trying something that you don't like&lt;/strong&gt; very much tends to make it slightly more appealing and &lt;strong&gt;broaden your perspective&lt;/strong&gt;, and even though you may never decide to use it in a real project, you might come to &lt;strong&gt;understand in which situations that language or methodology could actually be the right choice&lt;/strong&gt;. It's OK to have favorites, but to really develop yourself, &lt;strong&gt;you have to stop hating&lt;/strong&gt; and do your best, even when you're not in your comfort zone. Learn a new language, try to change something in your processes, listen to people you used to ignore (or vilify) and try to &lt;strong&gt;put yourself in their shoes&lt;/strong&gt; — I can assure you that you will become better at what you do!&lt;/p&gt;

&lt;p&gt;So, let’s &lt;strong&gt;keep discussing, even arguing about technology&lt;/strong&gt; — that’s fine! There's definitely a certain amount of team bonding involved in slamming that brand we all love to hate, call it JavaScript, PHP, Monoliths or anything else, but the next time you’re arguing with a colleague around making a decision, &lt;strong&gt;don’t let the hate or rejection make it for you&lt;/strong&gt;: try putting yourself in your colleague’s shoes and &lt;strong&gt;understand why they believe what they’re saying&lt;/strong&gt;. Do the exercise of &lt;strong&gt;inverting the discourse&lt;/strong&gt;, making yourself come up with a list of pros in addition to just cons. That could help you &lt;strong&gt;reach middle ground&lt;/strong&gt; and find alternatives that you’d never thought about. That’s how you &lt;strong&gt;become a better software engineer, enriching your opinions with diverse ways of thinking&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>diversity</category>
      <category>softwareengineering</category>
      <category>team</category>
    </item>
  </channel>
</rss>
