<?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>DEV Community: Lucas Lomeu</title>
    <description>The latest articles on DEV Community by Lucas Lomeu (@lucaslomeu).</description>
    <link>https://dev.to/lucaslomeu</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F641676%2Fa508a851-cde1-48f9-95d6-b120bbca5324.png</url>
      <title>DEV Community: Lucas Lomeu</title>
      <link>https://dev.to/lucaslomeu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lucaslomeu"/>
    <language>en</language>
    <item>
      <title>Hexagonal Architecture</title>
      <dc:creator>Lucas Lomeu</dc:creator>
      <pubDate>Tue, 21 Jul 2026 13:03:40 +0000</pubDate>
      <link>https://dev.to/lucaslomeu/hexagonal-architecture-3kne</link>
      <guid>https://dev.to/lucaslomeu/hexagonal-architecture-3kne</guid>
      <description>&lt;h2&gt;
  
  
  Hexagonal Architecture
&lt;/h2&gt;

&lt;p&gt;The main idea is relatively simple: business rules should be at the center of the application and shouldn't depend on the technologies around them.&lt;/p&gt;

&lt;p&gt;Databases, APIs, Kafka, Redis, web frameworks, and other technologies are important, of course, but from the application's point of view, they are external details.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is Hexagonal Architecture?
&lt;/h2&gt;

&lt;p&gt;Hexagonal Architecture was proposed by &lt;a href="https://alistaircockburn.com/" rel="noopener noreferrer"&gt;Alistair Cockburn&lt;/a&gt; with the idea that an application should be usable and testable independently of the technologies connected to it. In other words, our business rules shouldn't be directly coupled to external technologies.&lt;/p&gt;

&lt;p&gt;Let's take a simple example: Imagine an application with a feature for creating users. Today, it receives requests through a REST API and stores users in PostgreSQL.&lt;/p&gt;

&lt;p&gt;In the future, however, we might need to create users from Kafka messages, or maybe replace PostgreSQL with MongoDB.&lt;/p&gt;

&lt;p&gt;Ideally, none of these changes should require major changes to our business rules. This is exactly the kind of problem Hexagonal Architecture tries to solve.&lt;/p&gt;

&lt;p&gt;A simple way to visualize it is:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fztr564t7p8qy6kxuuriu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fztr564t7p8qy6kxuuriu.png" alt="Excalidraw Image" width="799" height="248"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;External technologies connect to our application through well-defined points called &lt;strong&gt;Ports&lt;/strong&gt;, while the components responsible for making those connections are called &lt;strong&gt;Adapters&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Application Core
&lt;/h2&gt;

&lt;p&gt;One of the most important ideas behind Hexagonal Architecture is protecting the &lt;strong&gt;core&lt;/strong&gt; of the application, because that's where the parts that represent the actual behavior of the system live.&lt;/p&gt;

&lt;p&gt;We can think of the core as having two main parts: the &lt;strong&gt;Domain&lt;/strong&gt;, which contains business concepts and rules, and the &lt;strong&gt;Application&lt;/strong&gt;, which contains the use cases responsible for coordinating those rules.&lt;/p&gt;

&lt;p&gt;Think about a banking system. The rule that an account cannot withdraw more money than its available balance belongs to the domain.&lt;/p&gt;

&lt;p&gt;On the other hand, "transfer money from account A to account B" is an application operation that needs to coordinate several steps to make that transfer happen.&lt;/p&gt;

&lt;p&gt;That use case might need to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Find account A.&lt;/li&gt;
&lt;li&gt;Find account B.&lt;/li&gt;
&lt;li&gt;Perform the debit and credit operations.&lt;/li&gt;
&lt;li&gt;Persist the changes.&lt;/li&gt;
&lt;li&gt;Publish an event.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;strong&gt;Use Case&lt;/strong&gt; is responsible for &lt;strong&gt;coordinating&lt;/strong&gt; this flow, while the important business rules remain in the domain.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Direction of Dependencies
&lt;/h2&gt;

&lt;p&gt;Dependencies should point toward the core, and the core shouldn't know about external details.&lt;/p&gt;

&lt;p&gt;For example, this would create unwanted coupling:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CreateUserService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;JpaRepository&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;UserEntity&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our application logic now knows directly about JPA, which means an infrastructure decision has leaked into the application core.&lt;/p&gt;

&lt;p&gt;With Hexagonal Architecture, we want to invert that dependency.&lt;/p&gt;

&lt;p&gt;Instead of having the core depend on JPA, the core defines what it needs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This interface knows nothing about JPA, Hibernate, PostgreSQL, MongoDB, or Spring Data. It simply says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"For my application to work, I need something capable of saving a user."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The infrastructure is responsible for deciding &lt;strong&gt;how&lt;/strong&gt; that will actually happen.&lt;/p&gt;

&lt;p&gt;This idea is closely related to the &lt;strong&gt;Dependency Inversion Principle&lt;/strong&gt;, the "D" in SOLID.&lt;/p&gt;




&lt;h2&gt;
  
  
  Ports
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Ports&lt;/strong&gt; are the communication points between the application core and the outside world. They are commonly divided into &lt;code&gt;Input Ports&lt;/code&gt; and &lt;code&gt;Output Ports&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Input Ports
&lt;/h3&gt;

&lt;p&gt;An Input Port represents an operation that the application exposes to the outside world. In Java, it can be represented by an interface that defines the contract of a use case.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;CreateUserUseCase&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CreateUserCommand&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This represents something our application knows how to do: create a user.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;REST Controller&lt;/code&gt; can call this port, but so can a &lt;code&gt;CLI&lt;/code&gt; or a &lt;code&gt;Kafka Consumer&lt;/code&gt;. None of them need to know the internal details of how the use case is implemented.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@RestController&lt;/span&gt;
&lt;span class="nd"&gt;@RequestMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/users"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserController&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;CreateUserUseCase&lt;/span&gt; &lt;span class="n"&gt;createUserUseCase&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;UserController&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CreateUserUseCase&lt;/span&gt; &lt;span class="n"&gt;createUserUseCase&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createUserUseCase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;createUserUseCase&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@PostMapping&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;UserResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="nd"&gt;@RequestBody&lt;/span&gt; &lt;span class="nc"&gt;CreateUserRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;
    &lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CreateUserCommand&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;createUserUseCase&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ok&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;UserResponse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt;
                &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt;
                &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getEmail&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
            &lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Output Ports
&lt;/h3&gt;

&lt;p&gt;Now imagine that our &lt;code&gt;CreateUserUseCase&lt;/code&gt; needs to save a user.&lt;/p&gt;

&lt;p&gt;To do that, the core needs to communicate with something external — in this case, a database. &lt;/p&gt;

&lt;p&gt;But there's an important detail here: the Use Case doesn't need to know &lt;strong&gt;which database is being used&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It only needs to express a requirement:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I need to save a user."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We can represent that requirement with an Output Port:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;existsByEmail&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can implement our use case:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CreateUserService&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;CreateUserUseCase&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt; &lt;span class="n"&gt;userRepository&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;CreateUserService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;UserRepository&lt;/span&gt; &lt;span class="n"&gt;userRepository&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;userRepository&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;userRepository&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CreateUserCommand&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;existsByEmail&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="o"&gt;()))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;EmailAlreadyExistsException&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;userRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that &lt;code&gt;CreateUserService&lt;/code&gt; knows about &lt;code&gt;UserRepository&lt;/code&gt;, but it knows nothing about &lt;code&gt;JpaRepository&lt;/code&gt;, Hibernate, PostgreSQL, or MongoDB.&lt;/p&gt;

&lt;p&gt;From the use case's point of view, those details don't matter.&lt;/p&gt;

&lt;p&gt;That decision belongs to the infrastructure.&lt;/p&gt;




&lt;h2&gt;
  
  
  Adapters
&lt;/h2&gt;

&lt;p&gt;If Ports define the communication points between the core and the outside world, &lt;strong&gt;Adapters&lt;/strong&gt; are responsible for connecting those points to specific technologies.&lt;/p&gt;

&lt;p&gt;They can be divided into two groups: &lt;code&gt;Input Adapters&lt;/code&gt; and &lt;code&gt;Output Adapters&lt;/code&gt;. An &lt;strong&gt;Input Adapter&lt;/strong&gt; starts an interaction with our application. A REST Controller, Kafka Consumer, or CLI are good examples. An Output Adapter connects our application to something external, such as PostgreSQL, MongoDB, Redis, or a Kafka Producer.&lt;/p&gt;

&lt;p&gt;There's an important distinction here:&lt;/p&gt;

&lt;p&gt;PostgreSQL itself is not an Adapter. The Adapter is the code responsible for connecting our application to PostgreSQL.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserRepositoryAdapter&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;SpringDataUserRepository&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;UserRepositoryAdapter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="nc"&gt;SpringDataUserRepository&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;
    &lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;repository&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;entity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;UserEntity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fromDomain&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;saved&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;saved&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toDomain&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;existsByEmail&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;existsByEmail&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we decide to use MongoDB tomorrow, we could create a &lt;code&gt;MongoUserRepositoryAdapter&lt;/code&gt; implementing the same &lt;code&gt;UserRepository&lt;/code&gt; interface.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;CreateUserService&lt;/code&gt; wouldn't need to change.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where Does the Domain Fit In?
&lt;/h2&gt;

&lt;p&gt;So far, we've talked a lot about the "core", but the domain and the application aren't exactly the same thing.&lt;/p&gt;

&lt;p&gt;Understanding this difference helps avoid a common mistake: putting every business rule inside Use Cases.&lt;/p&gt;

&lt;p&gt;Imagine we have an &lt;code&gt;Account&lt;/code&gt; entity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Account&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;AccountId&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Money&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;withdraw&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Money&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isGreaterThan&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;InsufficientBalanceException&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;subtract&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This validation shouldn't live in a Controller, a database, or a Use Case.&lt;/p&gt;

&lt;p&gt;It belongs to the rules of an account itself.&lt;/p&gt;

&lt;p&gt;The domain shouldn't need to depend on &lt;code&gt;@RestController&lt;/code&gt;, &lt;code&gt;@Entity&lt;/code&gt;, &lt;code&gt;@Repository&lt;/code&gt;, &lt;code&gt;KafkaTemplate&lt;/code&gt;, or &lt;code&gt;RedisTemplate&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ideally, the domain should be able to exist without even knowing that these technologies exist.&lt;/p&gt;




&lt;h2&gt;
  
  
  One Core, Different Technologies
&lt;/h2&gt;

&lt;p&gt;One interesting consequence of this decoupling is that we can connect different adapters to the same application core.&lt;/p&gt;

&lt;p&gt;Imagine we have a &lt;code&gt;CreateUserUseCase&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Today, it's called by a &lt;code&gt;REST API&lt;/code&gt;, but tomorrow we might add a &lt;code&gt;Kafka Consumer&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Both can use exactly the same Use Case.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4cfhpjnd2h6jbqq770os.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4cfhpjnd2h6jbqq770os.png" alt="Excalidraw Image" width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The same idea applies to the output side:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqvsymjhsl88ldke51egk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqvsymjhsl88ldke51egk.png" alt="Excalidraw Image" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;An in-memory adapter can also be useful for certain types of tests.&lt;/p&gt;

&lt;p&gt;This shows one of the original ideas behind the architecture quite well:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The application should be able to work regardless of how it is triggered or which technologies are connected to it."&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  When Does It Make Sense?
&lt;/h2&gt;

&lt;p&gt;Hexagonal Architecture tends to make more sense for applications with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Relevant business rules.&lt;/li&gt;
&lt;li&gt;Multiple integrations.&lt;/li&gt;
&lt;li&gt;Technologies that may need to be replaced or added over time.&lt;/li&gt;
&lt;li&gt;Different ways of interacting with the application.&lt;/li&gt;
&lt;li&gt;A strong need for isolated tests.&lt;/li&gt;
&lt;li&gt;Systems expected to live and evolve for a long time.&lt;/li&gt;
&lt;li&gt;A domain that needs to evolve independently from infrastructure.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Imagine, for example, a financial application that receives operations through &lt;code&gt;REST&lt;/code&gt;, &lt;code&gt;Kafka&lt;/code&gt;, or even &lt;code&gt;Batch&lt;/code&gt; jobs, while also communicating with PostgreSQL, Redis, Kafka, and external banking APIs.&lt;/p&gt;

&lt;p&gt;In this kind of system, controlling dependencies becomes increasingly important.&lt;/p&gt;

&lt;p&gt;On the other hand, for a small and simple CRUD application, a more traditional architecture might be more than enough.&lt;/p&gt;

&lt;p&gt;There's no reason to add architectural complexity just because a particular architecture is popular.&lt;/p&gt;

&lt;p&gt;The cost of the architecture also needs to be considered. Creating ports, adapters, and abstractions for every operation adds indirection to the code.&lt;/p&gt;

&lt;p&gt;That complexity should solve a real problem in the project.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Hexagonal Architecture isn't about creating more interfaces or following a specific folder structure.&lt;/p&gt;

&lt;p&gt;It's about controlling the direction of dependencies.&lt;/p&gt;

&lt;p&gt;For me, a simple way to summarize the idea is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your business rules should control the abstractions they need, instead of being controlled by the technologies they use.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the end, Ports, Adapters, Input, and Output are ways of putting this idea into practice.&lt;/p&gt;

&lt;p&gt;The exact structure can vary from project to project. What really matters is keeping clear boundaries between business logic and infrastructure.&lt;/p&gt;

&lt;p&gt;A few months ago, I implemented some of these concepts in a URL shortener as a study project. If you're curious, the code is available on &lt;a href="https://github.com/lucaslomeu/url-shortener" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>hexagonal</category>
      <category>java</category>
      <category>programming</category>
    </item>
    <item>
      <title>Building a Scalable URL Shortener</title>
      <dc:creator>Lucas Lomeu</dc:creator>
      <pubDate>Tue, 10 Feb 2026 11:08:45 +0000</pubDate>
      <link>https://dev.to/lucaslomeu/building-a-scalable-url-shortener-33ma</link>
      <guid>https://dev.to/lucaslomeu/building-a-scalable-url-shortener-33ma</guid>
      <description>&lt;p&gt;I thought a URL shortener was literally a simple CRUD. It turned out to be the exact opposite, so here’s how I designed and built mine.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Let's understand what we're building:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it does:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Convert &lt;code&gt;https://website.com/very/long/url&lt;/code&gt; into &lt;code&gt;short.com/aB3x&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Redirect users from short URL back to the original&lt;/li&gt;
&lt;li&gt;Handle 1,000+ writes/sec and 10,000+ reads/sec&lt;/li&gt;
&lt;li&gt;Never generate duplicate short codes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What makes it hard:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;IDs must be globally unique - no collisions&lt;/li&gt;
&lt;li&gt;Read-heavy workload - 10:1 read/write ratio&lt;/li&gt;
&lt;li&gt;Must scale horizontally&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Math Behind It
&lt;/h2&gt;

&lt;p&gt;Let's do some napkin math to understand scale:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;100 million URLs/day x (24 hours / 3600 ms) = &lt;strong&gt;~1,160 writes/sec&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;10:1 read ratio - 1,160 writes/sec x 10 = &lt;strong&gt;~11,600 reads/sec&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Over 10 years - 100M x 365 days * 10 years = &lt;strong&gt;~365 billion URLs&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Architecture: Hexagonal Pattern
&lt;/h2&gt;

&lt;p&gt;I chose &lt;strong&gt;Hexagonal Architecture&lt;/strong&gt; because it keeps the business logic independent from infrastructure. This makes it easier to swap databases, frameworks, or transport layers without touching the core of the application. It also aligns with what I’ve been studying lately, since I plan to dive deeper into this architecture and eventually write an article about it. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn6t4yxaqockohmgd6330.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn6t4yxaqockohmgd6330.png" alt="Hexagonal Architecture" width="799" height="393"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Database Choice: PostgreSQL
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Strong consistency&lt;/strong&gt; – Ensures there are no duplicate short codes, even during network partitions&lt;br&gt;
&lt;strong&gt;ACID transactions&lt;/strong&gt; – ID generation and insertion happen atomically&lt;br&gt;
&lt;strong&gt;Simple operations&lt;/strong&gt; – Around 99% of the queries are direct key lookups&lt;/p&gt;
&lt;h3&gt;
  
  
  Schema Design
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="n"&gt;SEQUENCE&lt;/span&gt; &lt;span class="n"&gt;urls_id_seq&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;urls&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;BIGINT&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="n"&gt;nextval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'urls_id_seq'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="n"&gt;short_code&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;UNIQUE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;long_url&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;created_at&lt;/span&gt; &lt;span class="n"&gt;TIMESTAMPTZ&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;UNIQUE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="n"&gt;idx_urls_short_code&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;urls&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;short_code&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Why this works:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;id&lt;/code&gt; is the source of truth (sequence-generated)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;short_code&lt;/code&gt; has unique index for fast &lt;strong&gt;O(log n)&lt;/strong&gt; lookups&lt;/li&gt;
&lt;li&gt;No index on &lt;code&gt;long_url&lt;/code&gt; (expensive, rarely queried)&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  The Core Problem: ID Generation
&lt;/h2&gt;

&lt;p&gt;Generating short codes sounds simple, but in practice you need IDs that:&lt;br&gt;
&lt;strong&gt;1.&lt;/strong&gt; Are globally &lt;strong&gt;unique&lt;/strong&gt; (no collisions)&lt;br&gt;
&lt;strong&gt;2.&lt;/strong&gt; Stay short (7 characters or less)&lt;br&gt;
&lt;strong&gt;3.&lt;/strong&gt; Don't require coordination between servers&lt;/p&gt;
&lt;h3&gt;
  
  
  Strategy: Sequence + Base62 Encoding
&lt;/h3&gt;

&lt;p&gt;Here's the actual implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ShortCodeGenerator&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;ShortCodeGeneratorPort&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;BASE62&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="s"&gt;"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ID must be positive"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="nc"&gt;StringBuilder&lt;/span&gt; &lt;span class="n"&gt;sb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StringBuilder&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;remainder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;62&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;sb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;append&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;BASE62&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;charAt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;remainder&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
            &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;/=&lt;/span&gt; &lt;span class="mi"&gt;62&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;sb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;reverse&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why this is collision-free:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PostgreSQL sequence guarantees &lt;strong&gt;unique&lt;/strong&gt; IDs (1, 2, 3, ...)&lt;/li&gt;
&lt;li&gt;Base62 is a bijective function: unique ID -&amp;gt; unique code&lt;/li&gt;
&lt;li&gt;If ID1 != ID2, then Base62(ID1) != Base62(ID2)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No retry logic needed&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Capacity Analysis
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Length&lt;/th&gt;
&lt;th&gt;Possible URLs&lt;/th&gt;
&lt;th&gt;Years at 1k/sec&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;5 chars&lt;/td&gt;
&lt;td&gt;916 million&lt;/td&gt;
&lt;td&gt;29 years&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6 chars&lt;/td&gt;
&lt;td&gt;56.8 billion&lt;/td&gt;
&lt;td&gt;1,800 years&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7 chars&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3.52 trillion&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;111,000 years&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;With 7 characters, we’re set for a while. We only need about 365 billion.&lt;/p&gt;




&lt;h2&gt;
  
  
  Caching
&lt;/h2&gt;

&lt;p&gt;At ~10k reads/sec, PostgreSQL was fine. But I knew the moment traffic spiked, the DB would start being the bottleneck.&lt;/p&gt;

&lt;p&gt;What surprised me the most was how visible the change became after adding cache.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Every request:
1. App -&amp;gt; PostgreSQL: "SELECT * FROM urls WHERE short_code = 'aB3x'"
2. PostgreSQL -&amp;gt; Disk: Read from index + table
3. PostgreSQL -&amp;gt; App: Return result
4. App -&amp;gt; Client: 302 redirect

Latency: 5-10ms per request
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even with indexes, disk I/O is expensive and most users keep hitting the same short URLs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution: Cache‑Aside with Redis
&lt;/h3&gt;

&lt;p&gt;The pattern is simple:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.&lt;/strong&gt; Try Redis first&lt;br&gt;
&lt;strong&gt;2.&lt;/strong&gt; If miss -&amp;gt; query in Database&lt;br&gt;
&lt;strong&gt;3.&lt;/strong&gt; Store in Redis for next time&lt;/p&gt;

&lt;p&gt;This gave me the best of both worlds: &lt;strong&gt;resilience&lt;/strong&gt; (if Redis dies, the system still works) and &lt;strong&gt;speed&lt;/strong&gt; (most reads never touch the DB).&lt;/p&gt;


&lt;h2&gt;
  
  
  API Design
&lt;/h2&gt;

&lt;p&gt;Keep it simple:&lt;/p&gt;
&lt;h3&gt;
  
  
  Create Short URL
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST /api/v1/shorten
Content-Type: application/json

{
  "url": "https://website.com/very/long/url"
}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"shortCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"aB3x"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Redirect
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /aB3x
GET /api/v1/aB3x
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Returns &lt;code&gt;302 Found&lt;/code&gt; with &lt;code&gt;Location: https://website.com/very/long/url&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why 302 instead of 301?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;301 &lt;strong&gt;(permanent)&lt;/strong&gt; gets cached by browsers -&amp;gt; no click tracking&lt;/li&gt;
&lt;li&gt;302 &lt;strong&gt;(temporary)&lt;/strong&gt; hits your server every time -&amp;gt; you can measure clicks or any metrics&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a URL shortener &lt;strong&gt;with analytics&lt;/strong&gt;, 302 is the right choice.&lt;/p&gt;




&lt;h2&gt;
  
  
  Code Structure
&lt;/h2&gt;

&lt;p&gt;Here's the actual file structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lomeu&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nc"&gt;UrlService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;         &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;orchestration&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;       &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;       &lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nc"&gt;UrlUseCase&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;     &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inbound&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;       &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;           &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nc"&gt;UrlRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;  &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outbound&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;           &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nc"&gt;ShortCodeGeneratorPort&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nc"&gt;Url&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;                    &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="n"&gt;domain&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;infrastructure&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nc"&gt;UrlController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;      &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;HTTP&lt;/span&gt; &lt;span class="n"&gt;adapter&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nc"&gt;Database&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;           &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nc"&gt;JdbcUrlRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;  &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;persistence&lt;/span&gt; &lt;span class="n"&gt;adapter&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;generator&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;       &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nc"&gt;ShortCodeGenerator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Base62&lt;/span&gt; &lt;span class="n"&gt;implementation&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nc"&gt;AppConfig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;
&lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nc"&gt;Main&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;                        &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;shutdown&lt;/span&gt; &lt;span class="n"&gt;hook&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;The complete implementation at &lt;a href="https://github.com/lucaslomeu/url-shortener" rel="noopener noreferrer"&gt;github.com/lucaslomeu/url-shortener&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>architecture</category>
      <category>java</category>
      <category>performance</category>
    </item>
    <item>
      <title>Arquitetura Fullstack com Angular 19 + Spring Boot</title>
      <dc:creator>Lucas Lomeu</dc:creator>
      <pubDate>Mon, 05 May 2025 11:11:21 +0000</pubDate>
      <link>https://dev.to/lucaslomeu/estudo-de-caso-arquitetura-de-um-app-fullstack-moderno-com-angular-19-e-spring-boot-3732</link>
      <guid>https://dev.to/lucaslomeu/estudo-de-caso-arquitetura-de-um-app-fullstack-moderno-com-angular-19-e-spring-boot-3732</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Neste post, compartilho um pouco da experiência de desenvolver uma aplicação fullstack real com Angular 19, Spring Boot e Docker.&lt;br&gt;&lt;br&gt;
O objetivo não é ensinar passo a passo, mas sim apresentar as decisões técnicas, aprendizados e desafios enfrentados ao longo do projeto.&lt;br&gt;&lt;br&gt;
Ao abordar tópicos como autenticação JWT, arquitetura, integração entre frontend e backend e containerização.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  📌 Sobre o projeto
&lt;/h2&gt;

&lt;p&gt;O &lt;strong&gt;Mony&lt;/strong&gt; é uma aplicação web para controle de assinaturas e finanças pessoais. A ideia é oferecer uma forma simples de:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cadastrar serviços recorrentes (como Netflix, Spotify, etc.)&lt;/li&gt;
&lt;li&gt;Visualizar todos os gastos mensais&lt;/li&gt;
&lt;li&gt;Ter uma visão clara sobre o orçamento&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;O foco desse projeto foi &lt;strong&gt;estruturar um app fullstack moderno&lt;/strong&gt; (por isso a escolha do Angular 19) com boas práticas de frontend, backend e containerização com Docker&lt;/p&gt;




&lt;h2&gt;
  
  
  🔧 Tecnologias utilizadas
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend:&lt;/strong&gt; Angular 19 + Tailwind CSS v4&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend:&lt;/strong&gt; Java 11 - Spring Boot + Spring Security + JWT + Spring Data JPA&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Banco de dados:&lt;/strong&gt; PostgreSQL 15&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Containerização:&lt;/strong&gt; Docker + Docker Compose&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧱 Arquitetura da aplicação
&lt;/h2&gt;

&lt;p&gt;Visão geral da arquitetura lógica da aplicação:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgfdfyzbbfr5oo6ri86ct.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgfdfyzbbfr5oo6ri86ct.png" alt="Arquitetura da aplicação" width="800" height="266"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🧬 Modelo de dados
&lt;/h2&gt;

&lt;p&gt;As entidades principais do sistema são &lt;code&gt;MonyUser&lt;/code&gt;, &lt;code&gt;Subscription&lt;/code&gt;, &lt;code&gt;Category&lt;/code&gt; e &lt;code&gt;Address&lt;/code&gt;. Veja como elas se relacionam:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftdu54c16t08dkwfmuyxe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftdu54c16t08dkwfmuyxe.png" alt="Modelo de Dados do Mony" width="607" height="828"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🗂️ Estrutura do Projeto
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mony/
├── server/        # Backend Spring Boot
│   └── ...        # Controllers, DTOs, Repositories, etc.
├── client/        # Frontend Angular 19
│   └── ...        # Features, Shared Modules, Layout
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A descrição completa das pastas e suas responsabilidades está disponível no &lt;a href="https://github.com/lucaslomeu/mony" rel="noopener noreferrer"&gt;README do repositório&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧰 Uso do Lombok no backend
&lt;/h2&gt;

&lt;p&gt;Durante o desenvolvimento do backend, utilizei o &lt;a href="https://projectlombok.org/" rel="noopener noreferrer"&gt;Project Lombok&lt;/a&gt; para reduzir o boilerplate nas classes Java, especialmente nas entidades, DTOs e serviços.&lt;/p&gt;

&lt;p&gt;Com anotações como &lt;code&gt;@Getter&lt;/code&gt;, &lt;code&gt;@Setter&lt;/code&gt;, &lt;code&gt;@NoArgsConstructor&lt;/code&gt;, &lt;code&gt;@AllArgsConstructor&lt;/code&gt; e &lt;code&gt;@Builder&lt;/code&gt;, consegui manter o código mais limpo, legível e focado na lógica de negócio, evitando repetições desnecessárias de métodos.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Além de deixar as classes mais enxutas, o uso do Lombok contribuiu para a produtividade e organização geral do projeto.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🔐 Autenticação JWT com Spring Security
&lt;/h2&gt;

&lt;p&gt;Implementei autenticação e autorização com JWT no backend, protegendo todos os endpoints sensíveis. A geração e validação dos tokens são feitas com filtro personalizado no Spring Security.&lt;/p&gt;

&lt;p&gt;No frontend, o Angular armazena o token localmente com LocalStorage e utiliza um &lt;code&gt;HTTPInterceptor&lt;/code&gt; para enviá-lo automaticamente em cada requisição autenticada.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;&lt;code&gt;Principal&lt;/code&gt; no backend&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;Durante a implementação, tive que decidir como lidar com os dados do usuário autenticado no backend.  &lt;/p&gt;

&lt;p&gt;Inicialmente, pensei em enviar o ID do usuário em cada requisição ou armazenar algo no &lt;code&gt;LocalStorage&lt;/code&gt;, mas isso abriria espaço para falhas de segurança.&lt;/p&gt;

&lt;p&gt;Foi nesse momento que conheci a interface &lt;code&gt;Principal&lt;/code&gt; do Spring — algo novo pra mim até então. Ela resolvia exatamente o que eu buscava: deixava o &lt;strong&gt;backend 100% responsável por identificar o usuário autenticado&lt;/strong&gt;, com base no JWT.  &lt;/p&gt;

&lt;p&gt;Isso permitiu que cada controller acessasse diretamente o contexto do usuário logado sem depender de nenhuma informação adicional do frontend.  &lt;/p&gt;

&lt;p&gt;Resultado: código mais limpo, seguro e desacoplado.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A partir disso, todos os controllers que precisam de contexto do usuário simplesmente recebem o &lt;code&gt;Principal&lt;/code&gt; como parâmetro. Com isso, o backend consegue filtrar ou associar dados automaticamente ao usuário autenticado, mantendo a integridade dos dados e a segurança da aplicação.&lt;/p&gt;




&lt;h2&gt;
  
  
  📦 Docker Compose: backend + frontend + PostgreSQL
&lt;/h2&gt;

&lt;p&gt;Para facilitar o desenvolvimento e isolar os serviços, configurei um ambiente completo com Docker Compose.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;PostgreSQL 15 (banco de dados)&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Spring Boot (backend)&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Angular 19 (frontend)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E com o comando abaixo, toda a aplicação sobe em containers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose up &lt;span class="nt"&gt;--build&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧠 Aprendizados e desafios técnicos
&lt;/h2&gt;

&lt;p&gt;Enquanto desenvolvia o Mony, tive a oportunidade de aprofundar e aplicar conceitos importantes em várias áreas do stack fullstack moderno:&lt;/p&gt;

&lt;h3&gt;
  
  
  🔷 Frontend (Angular 19)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Estruturei a aplicação com lazy loading e arquitetura modular por feature, seguindo boas práticas para escalabilidade.&lt;/li&gt;
&lt;li&gt;Usei o &lt;strong&gt;Tailwind CSS v4&lt;/strong&gt; para estilização rápida, com foco em produtividade e responsividade.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Como venho de projetos com versões mais antigas do Angular (8, 11, 14), esse projeto foi também uma oportunidade para aplicar &lt;strong&gt;as novidades das versões mais recentes&lt;/strong&gt;. Entre os destaques:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://angular.dev/api/core/inject" rel="noopener noreferrer"&gt;&lt;code&gt;inject()&lt;/code&gt;&lt;/a&gt;: substitui a injeção de dependência tradicional via construtor. O código ficou mais limpo e menos verboso, especialmente em componentes simples ou standalone.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://angular.dev/api/core/computed" rel="noopener noreferrer"&gt;&lt;code&gt;@computed()&lt;/code&gt;&lt;/a&gt;: facilita a criação de propriedades derivadas e reativas sem depender de &lt;code&gt;rxjs&lt;/code&gt;, tornando o código mais declarativo, previsível e legível.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://angular.dev/api/core/@for" rel="noopener noreferrer"&gt;&lt;code&gt;@for&lt;/code&gt;&lt;/a&gt; e &lt;a href="https://angular.dev/api/core/@if" rel="noopener noreferrer"&gt;@if&lt;/a&gt;: evoluções das diretivas estruturais (&lt;code&gt;*ngFor&lt;/code&gt;, &lt;code&gt;*ngIf&lt;/code&gt;) que tornam o HTML mais moderno e direto, eliminando a necessidade de blocos &lt;code&gt;ng-template&lt;/code&gt; e melhorando a performance.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://angular.dev/api/core/resource" rel="noopener noreferrer"&gt;resource()&lt;/a&gt;: uma das features que mais gostei (mesmo ainda sendo experimental). Permite declarar &lt;code&gt;loader&lt;/code&gt; e &lt;code&gt;request&lt;/code&gt; de forma reativa e integrada ao ciclo de vida, gerenciando chamadas assíncronas com muito menos código, utilizando &lt;code&gt;signals&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://angular.dev/api/core/effect" rel="noopener noreferrer"&gt;effect()&lt;/a&gt;: executa funções automaticamente sempre que um &lt;code&gt;signal&lt;/code&gt; dependente muda de valor. Usei no serviço de CEP, por exemplo, para atualizar campos dinamicamente conforme o usuário escolhia um estado, assim o DOM respondia instantaneamente.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🔶 Backend (Spring Boot)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Configuração completa do Spring Security com autenticação via JWT&lt;/li&gt;
&lt;li&gt;Implementação de filtros personalizados para validar tokens&lt;/li&gt;
&lt;li&gt;Uso da interface &lt;code&gt;Principal&lt;/code&gt; para identificar automaticamente o usuário logado sem expor dados no frontend&lt;/li&gt;
&lt;li&gt;Mapeamento e relacionamento de entidades com JPA, incluindo um cenário N:N usando &lt;code&gt;@ManyToMany&lt;/code&gt; com &lt;code&gt;@JoinTable&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Separação clara entre DTOs, entidades, serviços e repositórios&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🤝 Conclusão
&lt;/h2&gt;

&lt;p&gt;Você pode conferir o código completo aqui:&lt;br&gt;&lt;br&gt;
🔗 &lt;a href="https://github.com/lucaslomeu/mony" rel="noopener noreferrer"&gt;Repositório no GitHub - Mony&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  📋 Resumo técnico
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;✅ Stack: Angular 19, Spring Boot, PostgreSQL&lt;/li&gt;
&lt;li&gt;🧠 Auth: JWT + Spring Security + &lt;code&gt;Principal&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;🐳 Dev: Docker Compose com 3 containers&lt;/li&gt;
&lt;li&gt;🧰 Extras: Lombok, Tailwind, ng2-charts&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>angular</category>
      <category>jwt</category>
      <category>springboot</category>
      <category>docker</category>
    </item>
    <item>
      <title>Linux Basics: Essential Terminal Commands</title>
      <dc:creator>Lucas Lomeu</dc:creator>
      <pubDate>Mon, 13 Nov 2023 11:44:37 +0000</pubDate>
      <link>https://dev.to/lucaslomeu/basic-linux-ch3</link>
      <guid>https://dev.to/lucaslomeu/basic-linux-ch3</guid>
      <description>&lt;h2&gt;
  
  
  Linux Terminal Commands
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Listing
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;ls&lt;/code&gt; command is used to list files and directories. Here are some common options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;-a&lt;/strong&gt; or &lt;strong&gt;--all&lt;/strong&gt;: Lists all files, including hidden files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;-l&lt;/strong&gt;: Displays additional information about files and directories.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;-h&lt;/strong&gt;: Formats file sizes in a human-readable format.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;-R&lt;/strong&gt;: Lists directories and their contents recursively.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;path] &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="nt"&gt;-h&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="nt"&gt;-h&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Change Directory
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;cd&lt;/code&gt; command is used to navigate between directories.&lt;/p&gt;

&lt;p&gt;To go back to the parent directory, use &lt;code&gt;..&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;path]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To go back one directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ..
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Copy
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;cp&lt;/code&gt; command is used to copy files or directories to another location. The &lt;code&gt;-r&lt;/code&gt; option is used to copy directories and their contents recursively.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;source&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;destination]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Move
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;mv&lt;/code&gt; command is used to move files or directories to another location. It can also be used to rename files and directories.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mv&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;source&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;destination]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Remove
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;rm&lt;/code&gt; command is used to remove files or directories. The &lt;code&gt;-r&lt;/code&gt; option removes directories and their contents recursively, while &lt;code&gt;-f&lt;/code&gt; forces the operation without prompting for confirmation.&lt;/p&gt;

&lt;p&gt;Use this command carefully, especially when using &lt;code&gt;-r&lt;/code&gt; and &lt;code&gt;-f&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;path or file]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Make Directory
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;mkdir&lt;/code&gt; command creates a new directory. You can provide either the full path or just the directory name.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;path]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Remove Directory
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;rmdir&lt;/code&gt; command removes an empty directory. You can provide either the full path or just the directory name.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;rmdir&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;path]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Empty File
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;touch&lt;/code&gt; command can be used to create an empty file with the specified name.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;file]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Text Editor
&lt;/h3&gt;

&lt;p&gt;You can open and edit text files directly from the terminal using a text editor such as &lt;code&gt;nano&lt;/code&gt; or &lt;code&gt;vi&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nano &lt;span class="o"&gt;[&lt;/span&gt;file]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vi &lt;span class="o"&gt;[&lt;/span&gt;file]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Superuser
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;sudo&lt;/code&gt; command is used to execute commands with elevated privileges.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;command&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Clear
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;clear&lt;/code&gt; command clears the terminal screen.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;clear
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>linux</category>
      <category>terminal</category>
      <category>beginners</category>
      <category>learning</category>
    </item>
    <item>
      <title>Promises em JavaScript: entendendo o básico</title>
      <dc:creator>Lucas Lomeu</dc:creator>
      <pubDate>Sun, 13 Mar 2022 17:03:30 +0000</pubDate>
      <link>https://dev.to/lucaslomeu/entendendo-promises-2al5</link>
      <guid>https://dev.to/lucaslomeu/entendendo-promises-2al5</guid>
      <description>&lt;h1&gt;
  
  
  PROMISES
&lt;/h1&gt;

&lt;p&gt;Antes de entendermos as &lt;code&gt;Promises&lt;/code&gt;, temos de conhecer as diferenças entre comportamentos &lt;code&gt;síncronos&lt;/code&gt; e &lt;code&gt;assíncronos&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Síncrono e Assíncrono
&lt;/h2&gt;

&lt;p&gt;Como o próprio nome pode nos ajudar a deduzir, &lt;strong&gt;síncrono&lt;/strong&gt; acontece em sincronia, ou seja, que ocorre em mesmo tempo que outra coisa. Já &lt;strong&gt;assíncrono&lt;/strong&gt; é o oposto, é algo que não acontece junto com outra coisa. Podemos exemplificar esses comportamentos síncronos e assíncronos, como uma chamada de telefone e envio de e-mail, respectivamente.&lt;/p&gt;

&lt;p&gt;Sabendo o básico, podemos afirmar que o &lt;strong&gt;Javascript&lt;/strong&gt; é &lt;strong&gt;síncrono&lt;/strong&gt;, sendo executado linearmente de cima para baixo. Isso se deve ao fato que ela é uma linguagem &lt;code&gt;Single Thread&lt;/code&gt;, então cada linha de comando só será executada quando a anterior é finalizada.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&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;Primeira linha&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="nf"&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;Segunda linha&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="nf"&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;Terceira linha&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="nf"&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;Quarta linha&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="nf"&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;Quinta linha&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sendo assim, o código acima quando executado, nos retorna:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Primeira&lt;/span&gt; &lt;span class="nx"&gt;linha&lt;/span&gt;
&lt;span class="nx"&gt;Segunda&lt;/span&gt; &lt;span class="nx"&gt;linha&lt;/span&gt;
&lt;span class="nx"&gt;Terceira&lt;/span&gt; &lt;span class="nx"&gt;linha&lt;/span&gt;
&lt;span class="nx"&gt;Quarta&lt;/span&gt; &lt;span class="nx"&gt;linha&lt;/span&gt;
&lt;span class="nx"&gt;Quinta&lt;/span&gt; &lt;span class="nx"&gt;linha&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No Javascript temos a função assíncrona &lt;code&gt;setTimeout()&lt;/code&gt;, onde no primeiro parâmetro ela espera uma função e no segundo o tempo que após ser feita a chamada da função, ela será executada, isso em milissegundos.&lt;/p&gt;

&lt;p&gt;Sendo assim, vamos analisar o código abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&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;Primeira linha&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="nf"&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;Segunda linha&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;setTimeout&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&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;setTimeout&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="mi"&gt;2000&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="nf"&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;Terceira linha&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="nf"&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;Quarta linha&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="nf"&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;Quinta linha&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Caso a função &lt;code&gt;setTimeout()&lt;/code&gt; fosse &lt;em&gt;síncrona&lt;/em&gt;, deveriamos ter o retorno abaixo, já que está sendo chamado na terceira linha:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Primeira linha
Segunda linha
setTimeout
Terceira linha
Quarta linha
Quinta linha
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Porém, ela é uma função que não acontece junto com outra coisa -&lt;em&gt;assíncrona&lt;/em&gt; - ela só sera retornada com uma condição ou parâmetro, que no caso, é ser executada após 2 segundos, nos retornando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Primeira linha
Segunda linha
Terceira linha
Quarta linha
Quinta linha
setTimeout
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ou seja, ela executa todas as outras linhas de maneira &lt;em&gt;síncrona&lt;/em&gt;, quando chega no &lt;code&gt;setTimeout()&lt;/code&gt;, ela é entregue para uma request &lt;strong&gt;separada&lt;/strong&gt; que é executada fora da thread do Javascript &lt;em&gt;- lembrando que o código que escrevemos é executado em uma única thread -&lt;/em&gt; fazendo com que o restante continue a ser executado.&lt;/p&gt;

&lt;p&gt;Agora já com o conhecimento de &lt;strong&gt;síncrono/assíncrono&lt;/strong&gt;, podemos tratar das &lt;code&gt;Promises&lt;/code&gt;. Como o próprio nome diz, é uma promessa que pode ou não estar disponível em algum momento, sendo assim, ela possui um comportamento &lt;strong&gt;assíncrono&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Promise é um objeto que possui três possíveis estados, sendo eles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pending&lt;/strong&gt; – Estado inicial, pendente de execução&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fulfilled&lt;/strong&gt; – Concluido com sucesso&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rejected&lt;/strong&gt; – Ocorreu algum erro&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A mesma recebe &lt;strong&gt;dois parâmetros&lt;/strong&gt;, sendo eles comumente chamados de &lt;code&gt;resolve e reject&lt;/code&gt;, sendo assim, apenas um dos métodos de tratamento será chamado. Para acessar a resposta dessa promisse, temos o &lt;code&gt;.then&lt;/code&gt; e o &lt;code&gt;.catch&lt;/code&gt;, sendo responsáveis por tratar a resposta e o erro respectivamente.&lt;/p&gt;

&lt;p&gt;O método &lt;code&gt;.then&lt;/code&gt; irá registrar um _callback _de &lt;strong&gt;sucesso&lt;/strong&gt; e é comum executar duas ou mais operações assíncronas consecutivas, executando a ação posterior apenas quando a anterior for bem sucedida, isso é possível realizando o encadeamento do método &lt;code&gt;.then&lt;/code&gt;, onde o mesmo retorna uma nova promise diferente da original.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&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;Inicio da Promise&lt;/span&gt;&lt;span class="dl"&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;numero&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numero&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="nf"&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Primeiro valor: &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="s2"&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;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="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;newValue&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Valor somado de 5: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;newValue&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;No código foi chamado a função construtora passando os dois parâmetros como argumento e a chamada de uma função callback.&lt;br&gt;
Logo de  início já é executado nosso primeiro &lt;code&gt;console.log&lt;/code&gt; e o armazenamento de &lt;em&gt;numero&lt;/em&gt; em uma constante, recebendo o valor 10, logo após chamamos nosso &lt;code&gt;resolve(numero)&lt;/code&gt;, passando como resolvida nossa promise e ela recebe esse número.&lt;/p&gt;

&lt;p&gt;Agora devemos tratar esse resultado fazendo a chamada do nosso primeiro &lt;code&gt;.then&lt;/code&gt; onde o mesmo recebe um parâmetro &lt;code&gt;value&lt;/code&gt;, esse valor recebe o que foi passado em resolve, logo &lt;code&gt;value&lt;/code&gt; equivale a &lt;code&gt;numero&lt;/code&gt;, sendo assim, chamamos o &lt;code&gt;console.log&lt;/code&gt; desse &lt;code&gt;value&lt;/code&gt; e retornamos ele para que possamos utilizar no próximo encadeamento de &lt;code&gt;.then&lt;/code&gt;, onde iremos tratar o retorno anterior.&lt;br&gt;
Para diferenciarmos, foi passado como parâmetro agora &lt;code&gt;newValue&lt;/code&gt; onde o mesmo recebeu o valor anterior e será tratado no console, sendo acrescido de 5.&lt;/p&gt;

&lt;p&gt;O resultado final desse código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&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;Inicio da Promise&lt;/span&gt;&lt;span class="dl"&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;numero&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numero&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="nf"&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Primeiro valor: &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="s2"&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;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="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;newValue&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Valor somado de 5: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;newValue&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;Agora iremos tratar a promise caso fosse chamado o &lt;code&gt;reject&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&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;Inicio da Promise&lt;/span&gt;&lt;span class="dl"&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;numero&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Número não identificado&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="p"&gt;.&lt;/span&gt;&lt;span class="nf"&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Primeiro valor: &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="s2"&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;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="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;newValue&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Valor somado de 5: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;newValue&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Houve um erro: &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="s2"&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;Como fazemos a chamada de &lt;code&gt;reject()&lt;/code&gt;, a função logo irá chamar o método &lt;code&gt;.catch&lt;/code&gt; que também recebe um parâmetro e o mesmo é retornado no &lt;code&gt;console.log()&lt;/code&gt;, renderizando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Inicio da Promise
Houve um erro: Número não identificado
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Um método muito utilizado, é a API fetch que realiza requisições HTTP através de Promises.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>promises</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Todo List com React: passo a passo</title>
      <dc:creator>Lucas Lomeu</dc:creator>
      <pubDate>Tue, 16 Nov 2021 23:36:56 +0000</pubDate>
      <link>https://dev.to/lucaslomeu/criando-todolist-com-reactjs-1k88</link>
      <guid>https://dev.to/lucaslomeu/criando-todolist-com-reactjs-1k88</guid>
      <description>&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;Nesse tutorial iremos desenvolver um &lt;strong&gt;"TodoList"&lt;/strong&gt; em ReactJs da maneira mais simples possível, sendo assim, não iremos focar em estilização do mesmo. Recomendo que tenha noção básica de &lt;em&gt;JavaScript&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Criando o projeto
&lt;/h2&gt;

&lt;p&gt;Para iniciarmos o projeto, abra seu terminal e use o seguinte comando&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-react-app todolist
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Após a criação, dirija-se até o diretório e abra seu VisualStudio Code&lt;/p&gt;

&lt;h2&gt;
  
  
  Limpando arquivos desnecessários
&lt;/h2&gt;

&lt;p&gt;Para esse tutorial, poderemos remover alguns arquivos desnecessários de nossa aplicação.&lt;/p&gt;

&lt;p&gt;Na pasta &lt;strong&gt;src&lt;/strong&gt;, remova os arquivos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;App.test.js
index.css
logo.svg
reportWebVitals.js
setupTests.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Você também deverá retirar a importação desses arquivos no &lt;strong&gt;App.js&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Parte 01
&lt;/h2&gt;

&lt;p&gt;Logo de início deveremos fazer a importação do &lt;strong&gt;useState&lt;/strong&gt; no &lt;strong&gt;App.js&lt;/strong&gt;, pois estamos desenvolvendo um &lt;strong&gt;TodoList&lt;/strong&gt;, ou seja, teremos alterações de estado (adição, remoção) de itens na lista de afazeres.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assim, estaremos aptos a utilizar o Hook.&lt;/p&gt;

&lt;p&gt;Agora, deveremos criar o estado inicial da lista, para isso, utilizamos o &lt;strong&gt;useState&lt;/strong&gt;, sendo um hook que retorna um array com dois valores, o primeiro é o estado atual e imutável, já o segundo uma função que irá alterar o estado do componente quando a mesma for ativada.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTodo&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;-Todo&lt;/strong&gt; representa o primeiro valor, logo o estado atual.&lt;br&gt;
&lt;strong&gt;-setTodo&lt;/strong&gt; representa o segundo valor, logo a função que irá realizar as alterações. &lt;em&gt;(Por padrão costumamos nomear o segundo valor com "set" e logo após o nome dado ao primeiro valor).&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;O valor entre parenteses do &lt;em&gt;useState&lt;/em&gt; representa o valor &lt;strong&gt;INICIAL&lt;/strong&gt; do estado, como estamos criando uma lista de afazeres, o valor inicial é um Array que poderá conter vários itens.&lt;/p&gt;

&lt;p&gt;Agora iremos criar outro estado para os &lt;strong&gt;novos&lt;/strong&gt; itens a serem adicionados nesse array:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;newTodo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setNewTodo&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Dessa vez o estado inicial é uma &lt;em&gt;string&lt;/em&gt; vazia, pois é o valor inicial do input do tipo texto que iremos inserir na nossa aplicação.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Parte 02
&lt;/h2&gt;

&lt;p&gt;Com nossos estados criados, iremos desenvolver o que será renderizado, para isso adicionaremos um &lt;strong&gt;input&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTodo&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;newTodo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setNewTodo&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&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="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Todo&lt;/span&gt; &lt;span class="nx"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;
        &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;newTodo&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setNewTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&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="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;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;blockquote&gt;
&lt;p&gt;Para envolvermos várias tags &lt;em&gt;HTML&lt;/em&gt;, podemos utilizar uma &lt;strong&gt;div&lt;/strong&gt; ou então fragments &lt;strong&gt;&amp;lt;&amp;gt;&amp;lt;/&amp;gt;&lt;/strong&gt; e todo o conteudo dentro do mesmo.&lt;/p&gt;

&lt;p&gt;Criamos um input do tipo texto; no valor passamos o &lt;em&gt;newTodo&lt;/em&gt;, sendo identico ao do estado já criado e onChange passamos uma função, onde conforme o estado é alterado, ele atualiza seu valor (&lt;em&gt;value={newTodo}&lt;/em&gt;).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ou seja, o valor (texto) atual presente no input criado, será adicionado ao nosso estado, com isso poderemos futuramente fazer com que esse valor seja renderizado na lista de afazeres.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Para que possamos adicionar esse &lt;em&gt;valor&lt;/em&gt; em uma lista, iremos adicionar um botão que ao ser clicado, chamará a função &lt;em&gt;addNewTodo&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;addNewTodo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setTodo&lt;/span&gt;&lt;span class="p"&gt;([...&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newTodo&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="nf"&gt;setNewTodo&lt;/span&gt;&lt;span class="p"&gt;(&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Na &lt;strong&gt;primeira&lt;/strong&gt; linha, chamamos a função do nosso primeiro estado, onde seu valor inicial é um array vazio e definimos agora que seu valor será tudo que estava presente nesse array antes &lt;em&gt;(para isso utilizamos o spread)&lt;/em&gt;, e no segundo parâmetro passamos o &lt;em&gt;newTodo&lt;/em&gt;, ou seja, toda alteração que for feita nesse estado, após ser clicado no botão de "Adicionar", essa alteração/valor será adicionado ao nosso estado inicial da aplicação (todo).&lt;/p&gt;

&lt;p&gt;Já na &lt;strong&gt;segunda&lt;/strong&gt; linha, definimos que ao adicionar o novo valor no nosso estado, não podemos deixar o &lt;em&gt;valor/texto&lt;/em&gt; do nosso input com o que foi digitado, devemos retirar tudo e transformar nosso estado inicial em uma string vazia novamente.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;O &lt;strong&gt;botão&lt;/strong&gt; a ser criado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&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="nf"&gt;addNewTodo&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;Adicionar&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Recapitulando&lt;/strong&gt;: Ao ser clicado, chamará nossa função &lt;strong&gt;addNewTodo()&lt;/strong&gt;, que irá adicionar o novo valor ao nosso estado atual e logo após resetar o valor escrito no input.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Parte 03
&lt;/h2&gt;

&lt;p&gt;Agora iremos renderizar todos esses valores em uma lista, para isso utilizaremos o &lt;strong&gt;map&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ul&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;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;item&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;li&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;item&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
       &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/li&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;))}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ul&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ou seja, a cada item/todo/valor novo adicionado ao nosso array de &lt;em&gt;todos&lt;/em&gt;, o map irá percorrer essa lista de array e renderizar um por um em forma de lista. No código acima, passamos como parâmetro &lt;strong&gt;item&lt;/strong&gt;, sendo assim, cada &lt;strong&gt;item&lt;/strong&gt; presente no &lt;strong&gt;todo&lt;/strong&gt;, será renderizado um a um, até que o ultimo seja renderizado.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Escrevemos o código entre chaves pra mostrar que se trata de um código javascript e não HTML.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Com isso, chegamos a uma tela semelhante a essa:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxp6ihr254ocre5jz456b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxp6ihr254ocre5jz456b.png" alt="TodoList Render" width="291" height="219"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Parte 04
&lt;/h2&gt;

&lt;p&gt;Assim como podemos adicionar itens/afazeres ao nosso array, podemos também excluir o mesmo.&lt;/p&gt;

&lt;p&gt;Sendo assim, iremos criar dentro do &lt;strong&gt;map&lt;/strong&gt; um botão para que seja renderizado a cada item.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&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="nf"&gt;removeTodo&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="nx"&gt;Deletar&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como podemos ver, ao ser clicado ele chama a função &lt;em&gt;removeTodo&lt;/em&gt; que tem como parâmetro &lt;em&gt;index&lt;/em&gt;. Esse parâmetro nós podemos identificar ele no próprio map, é o segundo valor a ser passado na função.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;item&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;li&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;item&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&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="nf"&gt;removeTodo&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="nx"&gt;Deletar&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/li&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt; &lt;span class="p"&gt;))}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deveremos passar esse parâmetro também na função, para que possamos identificar o item. &lt;strong&gt;Ele funciona como identificador único, ID&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;removeTodo&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="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;tmpArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nx"&gt;tmpArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splice&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tmpArray&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;Criamos uma variável &lt;em&gt;tmpArray&lt;/em&gt;, que define um array temporário, onde utilizamos o &lt;em&gt;spread&lt;/em&gt; para adicionar tudo que contemos em nossa lista.&lt;/p&gt;

&lt;p&gt;Utilizamos o &lt;em&gt;splice&lt;/em&gt; e passamos como parâmetro o &lt;em&gt;index&lt;/em&gt; (identificador único que utilizamos como parâmetro na função e que passamos ele no map) e definimos que ele irá retirar apenas um item a partir do index 1.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;O método splice() altera o conteúdo de uma lista, adicionando novos elementos enquanto remove elementos antigos.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;E para finalizar, definimos o novo valor do estado &lt;em&gt;(setTodo)&lt;/em&gt;, com o valor do nosso array temporário &lt;em&gt;tmpArray&lt;/em&gt;, onde já foram feitas as modificações de exclusão de item.&lt;/p&gt;

&lt;h4&gt;
  
  
  Resultado da renderização
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff1hk784yui4qhx6h2lig.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff1hk784yui4qhx6h2lig.png" alt="TodoList Render" width="297" height="221"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Código Final
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTodo&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;newTodo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setNewTodo&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;addNewTodo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setTodo&lt;/span&gt;&lt;span class="p"&gt;([...&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newTodo&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="nf"&gt;setNewTodo&lt;/span&gt;&lt;span class="p"&gt;(&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;removeTodo&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="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;tmpArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nx"&gt;tmpArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splice&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tmpArray&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="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Todo&lt;/span&gt; &lt;span class="nx"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;
        &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;newTodo&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setNewTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&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="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&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="nf"&gt;addNewTodo&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;Adicionar&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ul&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;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;item&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;li&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;item&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&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="nf"&gt;removeTodo&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="nx"&gt;Deletar&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/li&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;))}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ul&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>react</category>
      <category>javascript</category>
      <category>braziliandevs</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
