<?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: Jonilson Sousa</title>
    <description>The latest articles on DEV Community by Jonilson Sousa (@jonilsonds9).</description>
    <link>https://dev.to/jonilsonds9</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F626012%2Fe533b8c9-4cfe-4dcc-b6bb-9a7aa17974e5.jpeg</url>
      <title>DEV Community: Jonilson Sousa</title>
      <link>https://dev.to/jonilsonds9</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jonilsonds9"/>
    <language>en</language>
    <item>
      <title>NestJS: Construindo o Módulo de Usuário — Parte 1: Salvando no banco</title>
      <dc:creator>Jonilson Sousa</dc:creator>
      <pubDate>Fri, 18 Apr 2025 01:05:42 +0000</pubDate>
      <link>https://dev.to/jonilsonds9/nestjs-construindo-o-modulo-de-usuario-parte-1-salvando-no-banco-c9a</link>
      <guid>https://dev.to/jonilsonds9/nestjs-construindo-o-modulo-de-usuario-parte-1-salvando-no-banco-c9a</guid>
      <description>&lt;p&gt;Continuando nossa série de artigos dominando o NestJS, hoje vamos aprender a criar um módulo de usuários, que é um dos módulos mais importantes em uma aplicação, pois é responsável por gerenciar os usuários da aplicação. Neste artigo, vamos aprender a criar o módulo e salvar um usuário no banco de dados usando o &lt;code&gt;bcrypt&lt;/code&gt; para fazer o hash da senha do usuário.&lt;/p&gt;

&lt;h3&gt;
  
  
  Módulo de usuários
&lt;/h3&gt;

&lt;p&gt;Para fazer a autenticação precisamos de usuários. Sendo assim, precisamos de uma entidade de usuário, bem como um &lt;code&gt;controller&lt;/code&gt; para gerenciar as requisições e um &lt;code&gt;service&lt;/code&gt; para gerenciar a lógica de gestão dos usuários, também precisamos de um &lt;code&gt;module&lt;/code&gt;, DTOs e tudo mais, é bastante coisa. Poderíamos então criar uma pasta &lt;code&gt;users&lt;/code&gt; dentro da pasta &lt;code&gt;src&lt;/code&gt; e criar os arquivos &lt;code&gt;user.entity.ts&lt;/code&gt;, &lt;code&gt;users.controller.ts&lt;/code&gt;, &lt;code&gt;users.service.ts&lt;/code&gt;, &lt;code&gt;users.module.ts&lt;/code&gt;. Mas o NestJS CLI já tem um comando para criar o módulo, com todos os componentes básicos necessários e com um comando vamos ganhar produtividade e velocidade. Para isso, basta executar comando &lt;code&gt;generate&lt;/code&gt; ou apenas &lt;code&gt;g&lt;/code&gt; do NestJS CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nest g resource &lt;span class="nb"&gt;users&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quando você executar o comando acima o NestJS CLI vai fazer algumas perguntas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What transport layer do you use&lt;/strong&gt;: Responda &lt;code&gt;REST API&lt;/code&gt; que é o que vamos usar.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Would you like to generate CRUD entry points&lt;/strong&gt;: Responda &lt;code&gt;Y&lt;/code&gt; para sim, para que ele crie os métodos básicos de CRUD.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Agora, o NestJS CLI vai criar a pasta &lt;code&gt;users&lt;/code&gt; dentro da pasta &lt;code&gt;src&lt;/code&gt; com os seguintes arquivos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nestjs-auth/
├── src/
│   ├── &lt;span class="nb"&gt;users&lt;/span&gt;/
│   │   ├── dto/
│   │   │   ├── create-user.dto.ts
│   │   │   ├── update-user.dto.ts
│   │   ├── entities/
│   │   │   └── user.entity.ts
│   │   ├── users.controller.spec.ts
│   │   ├── users.controller.ts
│   │   ├── users.module.ts
│   │   ├── users.service.spec.ts
│   │   └── users.service.ts
│   ├── ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Frxkvp4gcqn474en8o489.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%2Frxkvp4gcqn474en8o489.png" alt="Resource users criado" width="800" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O NestJS CLI gerou automaticamente os arquivos de teste e integrou o &lt;code&gt;UsersModule&lt;/code&gt; ao &lt;code&gt;AppModule&lt;/code&gt;. O próximo passo é configurar a tabela de usuários no banco de dados. No TypeORM, utilizamos entidades para esta finalidade - classes decoradas com &lt;code&gt;@Entity()&lt;/code&gt; que representam tabelas no banco. Este framework aproveita os decoradores do TypeScript para realizar o mapeamento entre classes e estruturas do banco de dados.&lt;/p&gt;

&lt;p&gt;Precisamos adicionar o decorator &lt;code&gt;@Entity()&lt;/code&gt; à classe &lt;code&gt;User&lt;/code&gt; gerada automaticamente. Embora o NestJS CLI tenha criado o arquivo &lt;code&gt;user.entity.ts&lt;/code&gt;, ele não incluiu este decorator necessário. Para configurar corretamente a entidade, o arquivo deve ser estruturado assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Entity&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;typeorm&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="nd"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O decorator &lt;code&gt;@Entity()&lt;/code&gt; recebe um objeto com diversas propriedades opcionais, eu gosto de usar a propriedade &lt;code&gt;name&lt;/code&gt; para definir o nome da tabela no banco de dados. O TypeORM por padrão usa o nome da classe todo em maiúsculo como nome da tabela (&lt;code&gt;user&lt;/code&gt;), mas &lt;code&gt;user&lt;/code&gt; passa a ideia de apenas um usuário, o que não faz muito sentido já que a tabela vai conter vários usuários. Por isso, eu gosto de usar o plural &lt;code&gt;users&lt;/code&gt; como nome da tabela.&lt;/p&gt;

&lt;p&gt;Certo, mas ainda não temos nenhuma coluna. Para isso, precisamos adicionar as propriedades que queremos que sejam colunas na tabela. Vamos adicionar as propriedades &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;email&lt;/code&gt; e &lt;code&gt;password&lt;/code&gt; na classe &lt;code&gt;User&lt;/code&gt;. A propriedade &lt;code&gt;id&lt;/code&gt; vai ser a chave primária da tabela, então precisamos adicionar o decorator &lt;code&gt;@PrimaryGeneratedColumn()&lt;/code&gt; do TypeORM, que já faz o mapeamento da propriedade &lt;code&gt;id&lt;/code&gt; como chave primária e também gera o valor automaticamente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PrimaryGeneratedColumn&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;typeorm&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="nd"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;PrimaryGeneratedColumn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As demais colunas são mapeadas usando o decorator &lt;code&gt;@Column()&lt;/code&gt;, que vincula propriedades da classe às colunas correspondentes na tabela. O TypeORM mantém o mesmo nome da propriedade ao criar a coluna no banco de dados. Este decorator aceita um objeto opcional de configuração com opções como &lt;code&gt;type&lt;/code&gt;, &lt;code&gt;nullable&lt;/code&gt;, &lt;code&gt;unique&lt;/code&gt; e &lt;code&gt;default&lt;/code&gt;. Por padrão, o TypeORM infere automaticamente o tipo da coluna baseado na propriedade - por exemplo, para propriedades do tipo &lt;code&gt;string&lt;/code&gt;, ele cria uma coluna &lt;code&gt;varchar(255)&lt;/code&gt; (dependendo do banco de dados). No entanto, é possível especificar explicitamente o tipo desejado através das configurações do decorator.&lt;/p&gt;

&lt;p&gt;Agora vamos adicionar as propriedades &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;email&lt;/code&gt;, &lt;code&gt;password&lt;/code&gt; e &lt;code&gt;role&lt;/code&gt; como colunas da tabela.  &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;password&lt;/code&gt; são apenas string, sendo assim não precisamos passar o tipo explicitamente. O TypeORM vai inferir o tipo da coluna a partir do tipo da propriedade. Já a coluna &lt;code&gt;email&lt;/code&gt; é uma string, mas queremos que seja única na tabela, então vamos passar a propriedade &lt;code&gt;unique&lt;/code&gt; no decorator para garantir que não haja dois usuários com o mesmo email. O TypeORM vai criar um índice único na coluna &lt;code&gt;email&lt;/code&gt;, o que garante que não haja duplicidade.&lt;/p&gt;

&lt;p&gt;Também vamos adicionar a propriedade &lt;code&gt;role&lt;/code&gt; que vai ser um enum, para isso vamos criar um arquivo &lt;code&gt;user.role.ts&lt;/code&gt; na pasta &lt;code&gt;src/users/entities&lt;/code&gt; por enquanto, e vamos criar um enum &lt;code&gt;UserRole&lt;/code&gt; com o seguinte código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;enum&lt;/span&gt; &lt;span class="nx"&gt;UserRole&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;ADMIN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="nx"&gt;INSTRUCTOR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="nx"&gt;STUDENT&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;O enum &lt;code&gt;UserRole&lt;/code&gt; vai conter os valores &lt;code&gt;ADMIN&lt;/code&gt;, &lt;code&gt;INSTRUCTOR&lt;/code&gt; e &lt;code&gt;STUDENT&lt;/code&gt;, que representam os papéis do usuário. Para isso, vamos adicionar a propriedade &lt;code&gt;role&lt;/code&gt; na classe &lt;code&gt;User&lt;/code&gt; e vamos passar o tipo &lt;code&gt;enum&lt;/code&gt; para o decorator &lt;code&gt;@Column()&lt;/code&gt;, também podemos passar o valor padrão &lt;code&gt;STUDENT&lt;/code&gt; para a coluna &lt;code&gt;role&lt;/code&gt;, assim todos os usuários que forem criados vão ter o papel de estudante por padrão.&lt;/p&gt;

&lt;p&gt;Agora, o arquivo &lt;code&gt;user.entity.ts&lt;/code&gt; vai ficar assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PrimaryGeneratedColumn&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;typeorm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;UserRole&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;./user.role&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="nd"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;PrimaryGeneratedColumn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
 &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

 &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
 &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

 &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;unique&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
 &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

 &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
 &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

 &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
   &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;enum&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;enum&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UserRole&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UserRole&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;STUDENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="p"&gt;})&lt;/span&gt;
 &lt;span class="nx"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UserRole&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;Para finalizar, é interessante ter o momento em que o usuário foi criado e atualizado. Para isso, podemos adicionar as propriedades &lt;code&gt;createdAt&lt;/code&gt; e &lt;code&gt;updatedAt&lt;/code&gt; na classe &lt;code&gt;User&lt;/code&gt;. O TypeORM tem os decorators &lt;code&gt;@CreateDateColumn()&lt;/code&gt; e &lt;code&gt;@UpdateDateColumn()&lt;/code&gt; que fazem isso automaticamente. O decorator &lt;code&gt;@CreateDateColumn()&lt;/code&gt; vai adicionar a data de criação do usuário e o decorator &lt;code&gt;@UpdateDateColumn()&lt;/code&gt; vai adicionar a data de atualização do usuário. Esses decorators vão criar as colunas &lt;code&gt;createdAt&lt;/code&gt; e &lt;code&gt;createdAt&lt;/code&gt; no banco de dados.&lt;/p&gt;

&lt;p&gt;Tanto o decorator &lt;code&gt;@CreateDateColumn()&lt;/code&gt; quanto o &lt;code&gt;@UpdateDateColumn()&lt;/code&gt; não tem nenhum parâmetro obrigatório. Por padrão, o TypeORM vai criar as colunas como &lt;code&gt;timestamp&lt;/code&gt; no banco de dados, no caso do PostgreSQL, o tipo &lt;code&gt;timestamp&lt;/code&gt; é o mesmo que &lt;code&gt;timestamp without time zone&lt;/code&gt;, ou seja, ele vai armazenar a data e hora sem o fuso horário e com precisão de 6 dígitos nos microssegundos, um exemplo de valor é &lt;code&gt;2024-10-17 14:35:22.123456&lt;/code&gt;. Então podemos passar &lt;code&gt;{ type: 'timestamptz', precision: 3 }&lt;/code&gt; para esses decorators, para que o TypeORM crie as colunas como &lt;code&gt;timestamp with time zone&lt;/code&gt;, com fuso horário e precisão de 3 dígitos nos milissegundos que já é o suficiente, um exemplo de valor é &lt;code&gt;2024-10-17 14:35:22.123-03&lt;/code&gt;. Com tudo isso a nossa classe &lt;code&gt;User&lt;/code&gt; deve ficar assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;CreateDateColumn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;PrimaryGeneratedColumn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;UpdateDateColumn&lt;/span&gt;&lt;span class="p"&gt;,&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;typeorm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;UserRole&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;./user.role&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="nd"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;PrimaryGeneratedColumn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;unique&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;enum&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;enum&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UserRole&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UserRole&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;STUDENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UserRole&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;CreateDateColumn&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;timestamptz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;precision&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;UpdateDateColumn&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;timestamptz&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;precision&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;updatedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&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;&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%2F0x7s2i37xe68reava1rp.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%2F0x7s2i37xe68reava1rp.png" alt="User.entity.ts e Enum UserRole" width="800" height="539"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agora, quando você subir a aplicação, o TypeORM vai criar a tabela &lt;code&gt;users&lt;/code&gt; no banco de dados com as colunas &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;email&lt;/code&gt;, &lt;code&gt;password&lt;/code&gt; e &lt;code&gt;role&lt;/code&gt;. Você pode verificar isso acessando o banco de dados:&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%2Ffhlsiv6pjx6o19iqtrl0.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%2Ffhlsiv6pjx6o19iqtrl0.png" alt="Tabela users criada" width="800" height="505"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Criando o repositório de usuários
&lt;/h3&gt;

&lt;p&gt;O TypeORM suporta o padrão de repositório, assim cada entidade tem um repositório associado a ela. O repositório é responsável por fazer as operações de CRUD (Create, Read, Update e Delete) no banco de dados e podemos conseguir o repositório através do &lt;code&gt;TypeOrmModule&lt;/code&gt; que já registramos no &lt;code&gt;DatabaseModule&lt;/code&gt;. O repositório é uma abstração que facilita o acesso ao banco de dados e permite que você trabalhe com as entidades de forma mais fácil e intuitiva.&lt;/p&gt;

&lt;p&gt;O repositório é uma classe que estende a classe &lt;code&gt;Repository&lt;/code&gt; do TypeORM e tem métodos para fazer as operações de CRUD no banco de dados. O repositório é injetado no &lt;code&gt;service&lt;/code&gt; e pode ser usado para fazer as operações de CRUD. Agora que temos a tabela de usuários criada, precisamos criar o repositório de usuários. O TypeORM já tem um repositório padrão que podemos usar, mas também podemos criar um repositório personalizado se quisermos.&lt;/p&gt;

&lt;p&gt;Para isso, precisamos importar o &lt;code&gt;TypeOrmModule&lt;/code&gt; no &lt;code&gt;UsersModule&lt;/code&gt; e usar o método &lt;code&gt;forFeature()&lt;/code&gt; para registrar o repositório de usuários. O método &lt;code&gt;forFeature()&lt;/code&gt; recebe um array com as entidades (&lt;code&gt;[User]&lt;/code&gt;) que queremos registrar no escopo atual, isso significa que o repositório de usuários só estará disponível no &lt;code&gt;UsersModule&lt;/code&gt; e não em outros módulos da aplicação. Nosso &lt;code&gt;users.module.ts&lt;/code&gt; deve ficar assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Module&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;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;UsersService&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;./users.service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;UsersController&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;./users.controller&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;TypeOrmModule&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;@nestjs/typeorm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;User&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;./entities/user.entity&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="nd"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;TypeOrmModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forFeature&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;])],&lt;/span&gt;
  &lt;span class="na"&gt;controllers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;UsersController&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;UsersService&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UsersModule&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F4t9uwr3l8qi4rrggw7iq.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%2F4t9uwr3l8qi4rrggw7iq.png" alt="UsersModule com forFeature" width="800" height="539"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agora já temos o repositório de usuários registrado no &lt;code&gt;UsersModule&lt;/code&gt;. O repositório de usuários pode ser injetado no &lt;code&gt;UsersService&lt;/code&gt; e pode ser usado para fazer as operações no banco de dados. O repositório é injetado através do construtor do &lt;code&gt;UsersService&lt;/code&gt;. Para isso, precisamos importar o &lt;code&gt;InjectRepository&lt;/code&gt; do &lt;code&gt;@nestjs/typeorm&lt;/code&gt; e o &lt;code&gt;Repository&lt;/code&gt; do &lt;code&gt;typeorm&lt;/code&gt;. O &lt;code&gt;InjectRepository&lt;/code&gt; é um decorator que indica que queremos injetar  um repositório, temos que passar como argumento o tipo do repositório que queremos injetar, no caso a entidade &lt;code&gt;User&lt;/code&gt;. O &lt;code&gt;Repository&lt;/code&gt; é a classe base do TypeORM para trabalhar com entidades, e precisamos indicar o tipo da entidade que queremos trabalhar, no caso &lt;code&gt;User&lt;/code&gt; usando o generics, ou seja, &lt;code&gt;Repository&amp;lt;User&amp;gt;&lt;/code&gt;. O &lt;code&gt;UsersService&lt;/code&gt; deve ficar assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Injectable&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;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;InjectRepository&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;@nestjs/typeorm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;User&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;./entities/user.entity&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Repository&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;typeorm&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="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UsersService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;InjectRepository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;userRepository&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Repository&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&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="p"&gt;{}&lt;/span&gt;

  &lt;span class="c1"&gt;// Métodos do service&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora temos o repositório de usuários injetado no &lt;code&gt;UsersService&lt;/code&gt; e podemos usar os métodos do repositório para fazer as operações no banco de dados. O repositório já tem os métodos básicos de CRUD prontos para serem usados, como &lt;code&gt;find()&lt;/code&gt;, &lt;code&gt;findOne()&lt;/code&gt;, &lt;code&gt;save()&lt;/code&gt;, &lt;code&gt;update()&lt;/code&gt;, &lt;code&gt;delete()&lt;/code&gt;, entre outros.&lt;/p&gt;

&lt;h3&gt;
  
  
  Salvando usuários no banco de dados
&lt;/h3&gt;

&lt;p&gt;Finalmente podemos começar a implementar os métodos do &lt;code&gt;UsersService&lt;/code&gt;. O primeiro método que vamos implementar é o método de criar usuário &lt;code&gt;create()&lt;/code&gt;. Este método recebe um DTO (Data Transfer Object) que representa os dados que queremos enviar a requisição para criar um usuário. Mas esse &lt;code&gt;CreateUserDto&lt;/code&gt; está vazio, então precisamos adicionar as propriedades que queremos que sejam enviadas na requisição para criar um usuário. O DTO deve conter as propriedades &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;email&lt;/code&gt;, &lt;code&gt;password&lt;/code&gt; e &lt;code&gt;role&lt;/code&gt;. O &lt;code&gt;role&lt;/code&gt; é um enum que representa o papel do usuário, então vamos usar o enum &lt;code&gt;UserRole&lt;/code&gt; que criamos anteriormente.&lt;/p&gt;

&lt;p&gt;Abra o arquivo &lt;code&gt;create-user.dto.ts&lt;/code&gt; que foi criado pelo NestJS CLI e adicione as propriedades:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;UserRole&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;../entities/user.role&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CreateUserDto&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="nl"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="nl"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="nl"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UserRole&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;Não se preocupe com a validação dos dados agora, vamos fazer no próximo artigo. Dando spoiler, vamos usar o pacote chamado &lt;code&gt;class-validator&lt;/code&gt; para validar os dados do DTO.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Agora podemos implementar o método &lt;code&gt;create()&lt;/code&gt; no &lt;code&gt;UsersService&lt;/code&gt; corretamente. O método &lt;code&gt;create()&lt;/code&gt; recebe um &lt;code&gt;CreateUserDto&lt;/code&gt; e usa o repositório de usuários para salvar o usuário no banco de dados. O método &lt;code&gt;save()&lt;/code&gt; do repositório salva o usuário. O método &lt;code&gt;create()&lt;/code&gt; deve ficar assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;createUserDto&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CreateUserDto&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;createUserDto&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;bcrypt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hashSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;createUserDto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&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="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;Aqui estamos usando o operador de espalhamento (&lt;code&gt;...&lt;/code&gt;) para copiar as propriedades do &lt;code&gt;createUserDto&lt;/code&gt; para um novo objeto. Isso é útil para evitar a mutação do objeto original e criar um novo objeto com as propriedades que queremos. E também fazemos o hash da senha do usuário para salvar o hash no banco em vez da senha em texto plano. Veja também que trocamos o método &lt;code&gt;create()&lt;/code&gt; do service para &lt;code&gt;async create()&lt;/code&gt;, isso porque o método &lt;code&gt;save()&lt;/code&gt; do repositório é assíncrono e precisamos esperar o resultado. O método &lt;code&gt;create()&lt;/code&gt; retorna o usuário criado no banco de dados.&lt;/p&gt;

&lt;p&gt;O método &lt;code&gt;save()&lt;/code&gt; do repositório recebe um objeto que representa o usuário que queremos salvar no banco de dados. O TypeORM vai mapear o objeto para a entidade &lt;code&gt;User&lt;/code&gt; e salvar no banco de dados. O método &lt;code&gt;save()&lt;/code&gt; retorna o usuário salvo no banco de dados, ou seja, o usuário com o id gerado pelo banco de dados.&lt;/p&gt;

&lt;p&gt;O &lt;code&gt;bcrypt.hashSync()&lt;/code&gt; é usado para fazer o hash da senha do usuário antes de salvar no banco de dados. O &lt;code&gt;bcrypt&lt;/code&gt; é um algoritmo de hash que é usado para proteger senhas. O método &lt;code&gt;hashSync()&lt;/code&gt; recebe a senha e o número de rounds ou salt (10) que é o custo do hash. O número de rounds indica quantas vezes o algoritmo vai fazer o hash da senha, quanto maior o número de rounds, mais seguro é o hash, mas também mais lento. O padrão é 10, mas você pode aumentar se quiser mais segurança.&lt;/p&gt;

&lt;p&gt;Não se esqueça de importar o &lt;code&gt;bcrypt&lt;/code&gt; no arquivo &lt;code&gt;users.service.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Outros imports&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;bcrypt&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;bcrypt&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;&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%2Fbpoh9dczi57bct2lia7r.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%2Fbpoh9dczi57bct2lia7r.png" alt="UserService com bcrypt" width="800" height="539"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Sim, estamos retornando o hash da senha do usuário, &lt;strong&gt;NÃO FAÇA ISSO EM PRODUÇÃO&lt;/strong&gt;, pois estamos expondo o hash da senha. O ideal seria retornar apenas o usuário criado sem a senha. Mas para simplificar, vamos deixar assim por enquanto. No próximo artigo vamos implementar a validação dos dados e também vamos usar o &lt;code&gt;class-transformer&lt;/code&gt; para transformar o objeto antes de retornar.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Problema com o bcrypt
&lt;/h3&gt;

&lt;p&gt;Ao tentar usar o &lt;code&gt;bcrypt&lt;/code&gt;, você pode se deparar com o seguinte erro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Cannot find module &lt;span class="s1"&gt;'.../bcrypt/lib/binding/napi-v3/bcrypt_lib.node'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Usuários do Node.js em versões recentes (como a v22.14.0) podem encontrar incompatibilidades com o &lt;code&gt;bcrypt&lt;/code&gt;. Isso ocorre porque a biblioteca depende de binários pré-compilados que podem não estar disponíveis para as últimas atualizações do Node.&lt;/p&gt;

&lt;p&gt;Uma alternativa é utilizar o &lt;code&gt;bcryptjs&lt;/code&gt;, uma implementação em JavaScript puro que não requer binários pré-compilados. Para fazer a migração, remova o &lt;code&gt;bcrypt&lt;/code&gt; e &lt;code&gt;@types/bcrypt&lt;/code&gt; do seu projeto e instale o &lt;code&gt;bcryptjs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm remove bcrypt @types/bcrypt
pnpm &lt;span class="nb"&gt;install &lt;/span&gt;bcryptjs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A transição é simples, pois o &lt;code&gt;bcryptjs&lt;/code&gt; mantém compatibilidade com a API original. Apenas atualize a importação em seu código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;bcrypt&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;bcryptjs&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;&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%2Fvd1i4mqq60hhjlqip8s9.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%2Fvd1i4mqq60hhjlqip8s9.png" alt="UserService com bcryptjs" width="800" height="539"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vale ressaltar que esta biblioteca já inclui suporte nativo ao TypeScript, dispensando instalações adicionais de tipos. Porém, conforme a documentação oficial, existe um trade-off: apesar da maior compatibilidade, o &lt;code&gt;bcryptjs&lt;/code&gt; apresenta performance cerca de 30% inferior à versão original:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;While bcrypt.js is compatible to the C++ bcrypt binding, it is written in pure JavaScript and thus slower (about 30%), effectively reducing the number of iterations that can be processed in an equal time span.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Você pode voltar a usar o &lt;code&gt;bcrypt&lt;/code&gt; quando o mesmo for atualizado para suportar as versões mais recentes do Node.js.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testando o método &lt;code&gt;create()&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Agora que temos o método &lt;code&gt;create()&lt;/code&gt; do &lt;code&gt;UsersService&lt;/code&gt; implementado, podemos testar se ele está funcionando corretamente. Como o NestJS já criou o &lt;code&gt;UsersController&lt;/code&gt; e implementou os métodos básicos de CRUD, podemos apenas adicionar uma nova request &lt;code&gt;POST&lt;/code&gt; no &lt;code&gt;api.http&lt;/code&gt; na raiz do projeto com o seguinte conteúdo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;### Criar usuário
POST http://localhost:3000/users
Content-Type: application/json

{
 "name": "Aluno",
 "email": "aluno1@mail.com",
 "password": "aluno123",
 "role": "STUDENT"
}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fqp5hlwy1wze4k54pcscl.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%2Fqp5hlwy1wze4k54pcscl.png" alt="Usuário criado com sucesso" width="800" height="539"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Executar a requisição. Você deve receber um status &lt;code&gt;201 Created&lt;/code&gt; e o usuário criado no banco de dados. Você pode verificar isso acessando o banco de dados e executando o seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fb76u61h2p5luowcucm80.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%2Fb76u61h2p5luowcucm80.png" alt="Usuário salvo no banco de dados" width="800" height="481"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusão
&lt;/h3&gt;

&lt;p&gt;Neste artigo, começamos a criar um módulo de usuários com o NestJS para salvar um usuário no banco de dados. Também aprendemos a usar o &lt;code&gt;bcrypt&lt;/code&gt; para fazer o hash da senha do usuário antes de salvar no banco de dados. Por hoje é só, até o próximo artigo!&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>nestjs</category>
      <category>typeorm</category>
      <category>postgres</category>
    </item>
    <item>
      <title>NestJS: Persistência de Dados com PostgreSQL e TypeORM</title>
      <dc:creator>Jonilson Sousa</dc:creator>
      <pubDate>Sat, 12 Apr 2025 22:32:51 +0000</pubDate>
      <link>https://dev.to/jonilsonds9/nestjs-persistencia-de-dados-com-postgresql-e-typeorm-18ge</link>
      <guid>https://dev.to/jonilsonds9/nestjs-persistencia-de-dados-com-postgresql-e-typeorm-18ge</guid>
      <description>&lt;p&gt;Vamos dar continuidade a nossa série de artigos dominando o NestJS. Neste artigo, vamos aprender a subir um banco de dados PostgreSQL com Docker e configurar o TypeORM no NestJS. Vamos também aprender a usar o &lt;code&gt;@nestjs/config&lt;/code&gt; para carregar as variáveis de ambiente do arquivo &lt;code&gt;.env&lt;/code&gt; e disponibilizá-las na aplicação.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pré-requisitos
&lt;/h2&gt;

&lt;p&gt;Você deve ter o projeto inicial do &lt;a href="https://dev.to/jonilsonds9/introducao-ao-nestjs-criando-sua-primeira-aplicacao-1plh"&gt;artigo anterior&lt;/a&gt; para acompanhar o artigo. Caso não tenha feito isso, recomendo que você faça as etapas do artigo anterior antes de continuar.&lt;/p&gt;

&lt;h2&gt;
  
  
  PostgreSQL com Docker Compose
&lt;/h2&gt;

&lt;p&gt;Para facilitar o desenvolvimento, vamos usar o PostgreSQL no Docker. Para isso vamos precisar do Docker instalado na sua máquina. Caso não tenha o Docker instalado, você pode usar a &lt;a href="https://docs.docker.com/engine/install/" rel="noopener noreferrer"&gt;documentação oficial&lt;/a&gt; para instalar.&lt;/p&gt;

&lt;p&gt;Com o Docker instalado, crie um arquivo &lt;code&gt;docker-compose.yml&lt;/code&gt; na raiz do seu projeto com o seguinte conteúdo:&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="na"&gt;postgres&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:16&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nestjs_postgres&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;TZ&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;America/Sao_Paulo'&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${DB_USER}&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${DB_PASSWORD}&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${DB_NAME}&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5432:5432"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.tmp/database:/var/lib/postgresql/data&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Certo, de forma proposital eu deixei variáveis de ambiente &lt;code&gt;DB_USER&lt;/code&gt;, &lt;code&gt;DB_PASSWORD&lt;/code&gt; e &lt;code&gt;DB_NAME&lt;/code&gt; em vez de valores fixos. Isso é uma boa prática, pois permite que você altere esses valores sem precisar modificar o código. Além disso, você pode usar diferentes valores para diferentes ambientes (desenvolvimento, teste, produção, etc.).&lt;/p&gt;

&lt;p&gt;Agora você pode criar um arquivo &lt;code&gt;.env&lt;/code&gt; na raiz do seu projeto para adicionar as variáveis de ambiente para o Docker Compose bem como para o NestJS. Inicialmente, o arquivo &lt;code&gt;.env&lt;/code&gt; deve conter as seguintes variáveis que precisamos para o Docker Compose:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DB_USER=postgres
DB_PASSWORD=postgres
DB_NAME=nestdb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora você pode iniciar o PostgreSQL com o Docker Compose. Execute o seguinte comando na raiz do seu projeto:&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;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso irá iniciar o PostgreSQL em segundo plano. Você pode verificar se o contêiner está em execução com o seguinte comando:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&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%2Fviz3klcd22pkury0ej6k.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%2Fviz3klcd22pkury0ej6k.png" alt="PostgreSQL rodando no Docker" width="800" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Você pode acessar o PostgreSQL usando o cliente &lt;code&gt;psql&lt;/code&gt; do Docker. Execute o seguinte comando para acessar o contêiner do PostgreSQL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; nestjs_postgres psql &lt;span class="nt"&gt;-U&lt;/span&gt; postgres &lt;span class="nt"&gt;-d&lt;/span&gt; nestdb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso irá abrir o cliente &lt;code&gt;psql&lt;/code&gt; dentro do contêiner do PostgreSQL. Você pode executar comandos SQL normalmente. Para sair do cliente &lt;code&gt;psql&lt;/code&gt;, digite &lt;code&gt;\q&lt;/code&gt; ou &lt;code&gt;exit&lt;/code&gt; e pressione Enter.&lt;/p&gt;

&lt;p&gt;Um ponto importante é que por padrão o PostgreSQL usa a "trust authentication" que significa que não é necessário senha para acessar o banco de dados de forma local. Nesse caso, executamos o comando &lt;code&gt;psql&lt;/code&gt; dentro do contêiner, e por isso não precisamos informar a senha. Já no caso da aplicação NestJS, precisamos informar a senha do banco de dados, já que a aplicação não está rodando dentro do contêiner e sim no nosso host.&lt;/p&gt;

&lt;h2&gt;
  
  
  Instalação das dependências
&lt;/h2&gt;

&lt;p&gt;O NestJS já tem um pacote &lt;code&gt;@nestjs/typeorm&lt;/code&gt; para facilitar a integração com o TypeORM sem gerar sobrecarga. O TypeORM é um ORM (Object-Relational Mapping) mais maduro disponível para Typescript. Ele nos permite trabalhar com bancos de dados relacionais de forma mais fácil e intuitiva.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Mas, poderíamos usar o Prisma, Sequelize ou qualquer outro ORM. O TypeORM é apenas uma opção que já vem integrada ao NestJS. Eu particularmente gosto do TypeORM, porque ele é &lt;code&gt;code-first&lt;/code&gt;, ou seja, você escreve o código e ele gera o banco de dados para você diferente do Prisma que é &lt;code&gt;schema-first&lt;/code&gt;, ou seja, você escreve o banco de dados e ele gera o código para você. Facilita a transição para alguém como eu que vem do mundo Java, onde o Hibernate é o ORM mais utilizado. Acho que a escolha do ORM depende muito do gosto pessoal e do projeto em si. O importante é escolher um ORM que atenda às suas necessidades e que você se sinta confortável em usar.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Para isso, vamos instalar o &lt;code&gt;@nestjs/typeorm&lt;/code&gt;, junto com o &lt;code&gt;typeorm&lt;/code&gt; de fato e driver do banco de dados que é pacote &lt;code&gt;pg&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm &lt;span class="nb"&gt;install&lt;/span&gt; @nestjs/typeorm typeorm pg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Podemos também já instalar o &lt;code&gt;bycrypt&lt;/code&gt; para fazer o hash da senha do usuário que vamos cadastrar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm &lt;span class="nb"&gt;install&lt;/span&gt; @nestjs/jwt bcrypt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Também vamos instalar o &lt;code&gt;@types/bcrypt&lt;/code&gt; para ter as definições de tipos do &lt;code&gt;bcrypt&lt;/code&gt; para o TypeScript. Isso é importante para evitar erros de tipos e ter uma melhor experiência de desenvolvimento com o TypeScript. Para isso, execute o seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; @types/bcrypt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configurando variáveis de ambiente no NestJS
&lt;/h2&gt;

&lt;p&gt;Sabemos que as variáveis de ambiente são uma boa prática para manter as informações sensíveis fora do código-fonte. Isso é especialmente importante em projetos que podem ser executados em diferentes ambientes (desenvolvimento, teste, produção, etc.).&lt;/p&gt;

&lt;p&gt;Em projeto Node.js, as variáveis de ambiente são acessadas através do objeto &lt;code&gt;process.env&lt;/code&gt;, entretanto temos que configurar o &lt;strong&gt;&lt;a href="https://www.npmjs.com/package/dotenv" rel="noopener noreferrer"&gt;dotenv&lt;/a&gt;&lt;/strong&gt; para que as variáveis de ambiente sejam carregadas corretamente. Você pode testar adicionando o seguinte código no seu &lt;code&gt;app.controller.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;getHello&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;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="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DB_NAME&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getHello&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;Ao executar a aplicação e acessar o &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;, você verá que o valor de &lt;code&gt;DB_NAME&lt;/code&gt; é &lt;code&gt;undefined&lt;/code&gt;. Isso acontece porque o dotenv não está configurado para carregar as variáveis de ambiente do arquivo &lt;code&gt;.env&lt;/code&gt;.&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%2Fihhazaqern34i8jaderx.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%2Fihhazaqern34i8jaderx.png" alt="Variável de ambiente undefined" width="800" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para configurar as variáveis de ambiente no NestJS, vamos usar o pacote &lt;code&gt;@nestjs/config&lt;/code&gt;. Esse pacote usa o &lt;strong&gt;&lt;a href="https://www.npmjs.com/package/dotenv" rel="noopener noreferrer"&gt;dotenv&lt;/a&gt;&lt;/strong&gt; internamente para carregar as variáveis de ambiente de um arquivo &lt;code&gt;.env&lt;/code&gt; e disponibilizá-las na aplicação. Para instalar o pacote &lt;code&gt;@nestjs/config&lt;/code&gt; use o seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm &lt;span class="nb"&gt;install&lt;/span&gt; @nestjs/config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Atualmente nosso &lt;code&gt;app.module.ts&lt;/code&gt; está com o seguinte código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Module&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;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AppController&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;./app.controller&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AppService&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;./app.service&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="nd"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="na"&gt;controllers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;AppController&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;AppService&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppModule&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora vamos configurar o &lt;code&gt;ConfigModule&lt;/code&gt; no nosso projeto. O &lt;code&gt;ConfigModule&lt;/code&gt; é o módulo responsável por carregar as variáveis de ambiente e disponibilizá-las na aplicação. Para isso, vamos importar o &lt;code&gt;ConfigModule&lt;/code&gt; no arquivo &lt;code&gt;app.module.ts&lt;/code&gt; e configurar o &lt;code&gt;isGlobal&lt;/code&gt; como &lt;code&gt;true&lt;/code&gt;, dentro da lista de &lt;code&gt;imports&lt;/code&gt; do &lt;code&gt;AppModule&lt;/code&gt; para que as variáveis de ambiente fiquem disponíveis em toda a aplicação:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Module&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;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AppController&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;./app.controller&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AppService&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;./app.service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ConfigModule&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;@nestjs/config&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="nd"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;ConfigModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forRoot&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
     &lt;span class="na"&gt;isGlobal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;controllers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;AppController&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;AppService&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppModule&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F79kg23dkxoewcyhgx13w.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%2F79kg23dkxoewcyhgx13w.png" alt="ConfigModule Global" width="800" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Configurando DatabaseModule com TypeORM
&lt;/h2&gt;

&lt;p&gt;Agora que temos as variáveis de ambiente configuradas, podemos começar a configurar o TypeORM. Temos duas abordagens possíveis: Podemos usar &lt;code&gt;providers&lt;/code&gt; e o TypeORM diretamente e deixar a configuração mais flexível, mas também mais complexa, verbosa e repetitiva, é útil quando temos mais de um banco de dados, ou contextos separados. Ou podemos usar o &lt;code&gt;TypeOrmModule&lt;/code&gt; do &lt;code&gt;@nestjs/typeorm&lt;/code&gt; que abstrai o TypeORM e o integra perfeitamente no ecossistema do NestJS, e também simplifica o acesso aos repositórios e descoberta de entidades e tudo mais. O que vamos fazer é usar o &lt;code&gt;TypeOrmModule&lt;/code&gt; com &lt;code&gt;forRootAsync&lt;/code&gt; e passar as configurações diretamente, mas usando o &lt;code&gt;ConfigService&lt;/code&gt; para acessar as variáveis de ambiente.&lt;/p&gt;

&lt;p&gt;Para isso, precisamos criar um módulo que vai conter a configuração do TypeORM. O que poderíamos fazer é importar o &lt;code&gt;TypeOrmModule&lt;/code&gt; no &lt;code&gt;AppModule&lt;/code&gt; e passar as configurações do banco de dados diretamente no &lt;code&gt;TypeOrmModule.forRoot()&lt;/code&gt;, mas isso não é uma boa prática, pois o &lt;code&gt;AppModule&lt;/code&gt; vai ficar muito grande e difícil de manter. Assim, vamos criar um módulo separado para o banco de dados. O NestJS tem um comando para criar módulos. Use o comando &lt;code&gt;generate&lt;/code&gt; ou apenas &lt;code&gt;g&lt;/code&gt; do NestJS CLI com a opção &lt;code&gt;module&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nest g module database
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O NestJS CLI vai criar a pasta &lt;code&gt;database&lt;/code&gt; dentro da pasta &lt;code&gt;src&lt;/code&gt; com o arquivo &lt;code&gt;database.module.ts&lt;/code&gt;, onde vamos configurar o &lt;code&gt;TypeOrmModule&lt;/code&gt; do &lt;code&gt;@nestjs/typeorm&lt;/code&gt; e também importar o &lt;code&gt;DatabaseModule&lt;/code&gt; no &lt;code&gt;AppModule&lt;/code&gt;. O arquivo &lt;code&gt;database.module.ts&lt;/code&gt; gerado deve ser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Module&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;@nestjs/common&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="nd"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;({})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DatabaseModule&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora vamos importar o &lt;code&gt;TypeOrmModule&lt;/code&gt; e usar o &lt;code&gt;forRootAsync&lt;/code&gt; dele para passar as configurações do banco de dados de forma assíncrona. Mas porque não usar o &lt;code&gt;forRoot&lt;/code&gt;? E a resposta é que o &lt;code&gt;forRootAsync&lt;/code&gt; é mais flexível e útil quando precisamos carregar as configurações de um arquivo &lt;code&gt;.env&lt;/code&gt; ou cofres de segredos externos como AWS Secrets Manager, Azure Key Vault, etc. O &lt;code&gt;forRoot&lt;/code&gt; é síncrono e pode não funcionar corretamente se as variáveis de ambiente não estiverem carregadas.&lt;/p&gt;

&lt;p&gt;Também vamos usar o &lt;code&gt;ConfigService&lt;/code&gt; do &lt;code&gt;@nestjs/config&lt;/code&gt; para acessar as variáveis de ambiente do arquivo &lt;code&gt;.env&lt;/code&gt;. O &lt;code&gt;ConfigService&lt;/code&gt; é um serviço que já vem com o &lt;code&gt;@nestjs/config&lt;/code&gt; e facilita o acesso às variáveis de ambiente, assim como conversão de valores e tudo mais.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Poderíamos usar o &lt;code&gt;forRoot&lt;/code&gt; do &lt;code&gt;TypeOrmModule&lt;/code&gt;, mas isso não é uma boa prática, pois o &lt;code&gt;forRoot&lt;/code&gt; é usado para passar as configurações de forma síncrona. O &lt;code&gt;forRootAsync&lt;/code&gt; é mais flexível e permite que você carregue as configurações de forma assíncrona, que é o que queremos fazer com o &lt;code&gt;ConfigService&lt;/code&gt; do  &lt;code&gt;ConfigModule&lt;/code&gt;. Vamos usar o &lt;code&gt;ConfigService&lt;/code&gt; para garantir que as variáveis de ambiente sejam carregadas corretamente quando a aplicação estiver pronta. O &lt;code&gt;ConfigService&lt;/code&gt; é o serviço responsável por carregar as variáveis de ambiente do arquivo &lt;code&gt;.env&lt;/code&gt; e disponibilizá-las na aplicação.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Vamos adicionar o &lt;code&gt;TypeOrmModule&lt;/code&gt; no &lt;code&gt;imports&lt;/code&gt; do &lt;code&gt;DatabaseModule&lt;/code&gt; e usar o &lt;code&gt;forRootAsync&lt;/code&gt; para passar as configurações do banco de dados. Precisamos agora dentro das configs do &lt;code&gt;TypeOrmModule&lt;/code&gt; importar o &lt;code&gt;ConfigModule&lt;/code&gt; e injetar o &lt;code&gt;ConfigService&lt;/code&gt; para acessar as variáveis de ambiente. Por fim, vamos usar o &lt;code&gt;useFactory&lt;/code&gt; para passar as configurações do banco de dados. O &lt;code&gt;useFactory&lt;/code&gt; é uma função que retorna as configurações do banco de dados. O &lt;code&gt;useFactory&lt;/code&gt; é chamado quando o módulo é carregado e o &lt;code&gt;ConfigService&lt;/code&gt; já está disponível.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Module&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;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ConfigModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ConfigService&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;@nestjs/config&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;TypeOrmModule&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;@nestjs/typeorm&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="nd"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;TypeOrmModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forRootAsync&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ConfigModule&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ConfigService&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;useFactory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ConfigService&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="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;postgres&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DB_HOST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;localhost&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DB_PORT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5432&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DB_USER&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DB_PASSWORD&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DB_NAME&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;entities&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/../**/*.entity{.ts,.js}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="na"&gt;synchronize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;NODE_ENV&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;production&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="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;TypeOrmModule&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DatabaseModule&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Veja que o &lt;code&gt;ConfigService&lt;/code&gt; já está injetado no &lt;code&gt;useFactory&lt;/code&gt; e podemos acessar as variáveis de ambiente através do método &lt;code&gt;get()&lt;/code&gt;. O método &lt;code&gt;get()&lt;/code&gt; recebe o nome da variável de ambiente e um valor padrão caso a variável não esteja definida. O &lt;code&gt;ConfigService&lt;/code&gt; já faz a conversão do tipo para o tipo desejado através do generics.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Todas as configurações são bastante autoexplicativas, mas vamos destacar duas&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;entities&lt;/code&gt;&lt;/strong&gt;: Array que contém os caminhos para as entidades do TypeORM. O &lt;code&gt;__dirname&lt;/code&gt; é uma variável global do Node.js que contém o caminho do diretório atual. O &lt;code&gt;+ '/../**/*.entity{.ts,.js}'&lt;/code&gt; é um padrão que indica que queremos carregar todas as entidades que terminam com &lt;code&gt;.entity.ts&lt;/code&gt; ou &lt;code&gt;.entity.js&lt;/code&gt; dentro do diretório pai (no caso o diretório &lt;code&gt;src&lt;/code&gt;) e em todos seus subdiretórios.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;synchronize&lt;/code&gt;&lt;/strong&gt;: Opção que faz com que o TypeORM sincronize o banco de dados com as entidades sempre que a aplicação for iniciada. Isso é útil para desenvolvimento, mas &lt;strong&gt;não é recomendado para produção&lt;/strong&gt;. Nesse caso, estamos usando a variável de ambiente &lt;code&gt;NODE_ENV&lt;/code&gt; para verificar se não estamos em produção. Se o &lt;code&gt;NODE_ENV&lt;/code&gt; for diferente de &lt;code&gt;production&lt;/code&gt;, o &lt;code&gt;synchronize&lt;/code&gt; será &lt;code&gt;true&lt;/code&gt;, caso contrário será &lt;code&gt;false&lt;/code&gt;. Isso significa que o banco de dados será sincronizado apenas em desenvolvimento ou testes. Em produção, você deve usar &lt;code&gt;migrations&lt;/code&gt; para atualizar o banco de dados.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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%2F90gvxqnvl0ukpi4eg0kx.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%2F90gvxqnvl0ukpi4eg0kx.png" alt="database.module.ts" width="800" height="520"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Lembre-se de adicionar a variável de ambiente &lt;code&gt;NODE_ENV&lt;/code&gt; no arquivo &lt;code&gt;.env&lt;/code&gt; para que o TypeORM saiba em qual ambiente está rodando. Para isso, adicione a seguinte linha no arquivo &lt;code&gt;.env&lt;/code&gt;:&lt;/p&gt;


&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NODE_ENV=development

DB_USER=postgres
DB_PASSWORD=postgres
DB_NAME=nestdb
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

&lt;p&gt;Agora tudo pronto! Você pode subir a aplicação e tudo deve funcionar normalmente. Mas como saber se a conexão com o banco está funcionando? Podemos apenas trocar uma das variáveis de ambiente, por exemplo, alterar a variável &lt;code&gt;DB_NAME&lt;/code&gt; no arquivo &lt;code&gt;.env&lt;/code&gt; para um nome de banco de dados que não existe. Ao subir a aplicação, o TypeORM deve dar um erro de conexão e a aplicação não vai subir.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusão
&lt;/h3&gt;

&lt;p&gt;Neste artigo, aprendemos a configurar o TypeORM com o PostgreSQL no NestJS. Também aprendemos a usar o &lt;code&gt;ConfigModule&lt;/code&gt; para carregar as variáveis de ambiente do arquivo &lt;code&gt;.env&lt;/code&gt; e disponibilizá-las na aplicação. Por hoje é isso, mas não se preocupe, ainda temos muito mais pela frente!&lt;/p&gt;

</description>
      <category>programming</category>
      <category>nestjs</category>
      <category>typeorm</category>
      <category>postgres</category>
    </item>
    <item>
      <title>Introdução ao NestJS: Criando sua primeira aplicação</title>
      <dc:creator>Jonilson Sousa</dc:creator>
      <pubDate>Thu, 03 Apr 2025 01:31:31 +0000</pubDate>
      <link>https://dev.to/jonilsonds9/introducao-ao-nestjs-criando-sua-primeira-aplicacao-1plh</link>
      <guid>https://dev.to/jonilsonds9/introducao-ao-nestjs-criando-sua-primeira-aplicacao-1plh</guid>
      <description>&lt;p&gt;Neste artigo, vamos ter uma visão geral do que é o NestJS, como ele funciona, por que você deve usá-lo e como criar sua primeira aplicação com este poderoso framework. E não se preocupe, não vamos ter muita enrolação, vamos direto ao ponto!&lt;/p&gt;

&lt;p&gt;Este artigo é o primeiro da série "Dominando o NestJS", onde exploramos os principais conceitos e funcionalidades do framework, além de criar projetos práticos.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que é o NestJS?
&lt;/h2&gt;

&lt;p&gt;O NestJS é um framework para construir aplicações Node.js escaláveis e eficientes, utilizando TypeScript. Construído sobre o Express, ele traz uma arquitetura modular, facilitando a organização e manutenção do código.&lt;/p&gt;

&lt;p&gt;Inspirado em conceitos de programação orientada a objetos, funcional e reativa, o NestJS é altamente extensível e permite integração com bibliotecas e ferramentas populares.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por que usar o NestJS?
&lt;/h2&gt;

&lt;p&gt;A resposta é simples: &lt;strong&gt;Produtividade e escalabilidade&lt;/strong&gt;. O NestJS oferece uma estrutura sólida e organizada para o desenvolvimento de aplicações, permitindo que você se concentre na lógica de negócios enquanto o framework cuida da parte estrutural. Com isso, você pode começar a desenvolver componentes reutilizáveis, facilitando a manutenção e a evolução do código.&lt;/p&gt;

&lt;p&gt;O NestJS também possui suporte nativo para TypeScript, o que traz benefícios como tipagem forte e melhor experiência no desenvolvimento. Com isso, podemos usar um linter e/ou Prettier para padronizar e manter o código limpo, facilitando para que outros desenvolvedores entendam e colaborem no projeto.&lt;/p&gt;

&lt;p&gt;A comunidade do NestJS é bastante ativa e está em crescimento. Você pode entrar diretamente no servidor do &lt;a href="https://discord.gg/G7Qnnhy" rel="noopener noreferrer"&gt;Discord&lt;/a&gt; do NestJS e tirar suas dúvidas com outros desenvolvedores. Ele também possui uma &lt;a href="https://docs.nestjs.com/" rel="noopener noreferrer"&gt;documentação&lt;/a&gt; completa e bem estruturada, o que facilita o aprendizado e a adoção do framework.&lt;/p&gt;

&lt;p&gt;Também é possível integrar o NestJS com outras tecnologias, como bancos de dados relacionais e não relacionais, filas de mensagens, autenticação, testes automatizados, entre outros. Isso torna o NestJS uma excelente escolha para projetos de todos os tamanhos e complexidades.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que você vai aprender nesta série?
&lt;/h2&gt;

&lt;p&gt;Nesta série, vamos explorar os principais conceitos e funcionalidades do NestJS, de forma prática e objetiva. Então, vamos entender e utilizar os seguintes recursos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Módulos&lt;/strong&gt;: Classe anotada com o decorator &lt;code&gt;@Module&lt;/code&gt;, que fornece metadados para organizar e gerenciar a estrutura do aplicativo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Controladores&lt;/strong&gt;: Cria rotas e manipula requisições HTTP, manipula parâmetros de rota, query strings e corpo das requisições.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Serviços&lt;/strong&gt;: Contém a lógica de negócios da aplicação, pode ser utilizado para injetar serviços em controladores e em outros serviços.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Injeção de dependência&lt;/strong&gt;: Facilita o gerenciamento de dependências entre componentes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Middleware&lt;/strong&gt;: Intercepta requisições e respostas, permitindo adicionar diversas funcionalidades, entre outras.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pipes&lt;/strong&gt;: Transformam e validam dados de entrada, permitindo garantir que os dados recebidos estejam no formato correto.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Guards&lt;/strong&gt;: Protegem rotas e recursos, permitindo implementar autenticação e autorização.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decorators&lt;/strong&gt;: Adicionam metadados a classes e métodos, facilitando a configuração de rotas, validação de dados, entre outros.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Suporte a tecnologias&lt;/strong&gt;: Integração com bancos de dados, autenticação, filas, testes automatizados, entre outros.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Pré-requisitos
&lt;/h2&gt;

&lt;p&gt;Chega de blá blá blá, vamos colocar a mão na massa! Primeiro de tudo, vamos aos pré-requisitos. Para seguir esta série, você precisa ter conhecimentos básicos de &lt;strong&gt;JavaScript&lt;/strong&gt; e &lt;strong&gt;TypeScript&lt;/strong&gt;, além de noções de desenvolvimento &lt;strong&gt;APIs RESTful&lt;/strong&gt;.&lt;br&gt;
E, claro, você deve ter o Node.js instalado na sua máquina.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Instalação do Node.js com NVM&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Você pode baixar a versão mais recente do Node.js &lt;a href="https://nodejs.org" rel="noopener noreferrer"&gt;aqui&lt;/a&gt;, recomendo usar o Node.js LTS (Long Term Support), que é a versão mais estável e recomendada para a maioria dos usuários.&lt;/p&gt;

&lt;p&gt;Você também pode usar o &lt;a href="https://github.com/nvm-sh/nvm" rel="noopener noreferrer"&gt;&lt;strong&gt;NVM&lt;/strong&gt; (Node Version Manager)&lt;/a&gt; para gerenciar as versões do Node.js na sua máquina e facilitar a sua vida no futuro. O NVM permite instalar e alterar entre diferentes versões do Node.js com facilidade. Para saber sobre a instalação do NVM, veja a &lt;a href="https://github.com/nvm-sh/nvm?tab=readme-ov-file#installing-and-updating" rel="noopener noreferrer"&gt;documentação oficial&lt;/a&gt;. Com o NVM instalado, você pode instalar a versão mais recente do Node.js com o seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nvm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--lts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se você tem mais de uma versão do Node.js instalada, você pode dizer ao NVM qual versão usar com o seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nvm use &lt;span class="nt"&gt;--lts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ou definir uma versão padrão para o NVM usar sempre que você abrir um novo terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nvm &lt;span class="nb"&gt;alias &lt;/span&gt;default &amp;lt;versão&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, se você executar o comando &lt;code&gt;node -v&lt;/code&gt;, você verá a versão do Node.js instalada na sua máquina.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Instalação do PNPM&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Recomendo usar o &lt;a href="https://pnpm.io/" rel="noopener noreferrer"&gt;&lt;strong&gt;PNPM&lt;/strong&gt;&lt;/a&gt; como gerenciador de pacotes, pois ele é mais rápido e eficiente do que o NPM e o Yarn. Como esse assunto foge um pouco do escopo deste artigo, não vou entrar em detalhes sobre o PNPM, mas você pode ler mais sobre ele na &lt;a href="https://pnpm.io/pt/motivation" rel="noopener noreferrer"&gt;documentação oficial&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;No caso do macOS, você pode instalar o PNPM com o Homebrew, que é um gerenciador de pacotes para o macOS com o seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;pnpm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se você estiver usando outro sistema operacional ou não quiser usar o Homebrew, você pode dar uma olhada na &lt;a href="https://pnpm.io/pt/installation" rel="noopener noreferrer"&gt;documentação de instalação do PNPM&lt;/a&gt; para ver todas as opções de instalação.&lt;/p&gt;

&lt;p&gt;Você também precisa fazer o setup do PNPM com o seguinte comando:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Instalação do NestJS CLI&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;O NestJS CLI é uma ferramenta de linha de comando que facilita a criação e gerenciamento de projetos NestJS. Com ele, você pode criar novos projetos, gerar componentes, executar testes, entre outras funcionalidades. Agora que você tem o Node.js e o PNPM instalados, você pode instalar o NestJS CLI globalmente com o seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm add &lt;span class="nt"&gt;-g&lt;/span&gt; @nestjs/cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Você deve ter o seguinte resultado:&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%2Fln3sp9zc7vnugop2vacz.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%2Fln3sp9zc7vnugop2vacz.png" alt="Instalação do NestJS CLI globalmente com o PNPM" width="800" height="507"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Você pode verificar se o NestJS CLI foi instalado corretamente executando o seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nest &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se tudo estiver certo, você verá a versão do NestJS CLI instalada na sua máquina.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. VSCode e Extensões&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Se, assim como eu, você é fã do Visual Studio Code, recomendo instalar as seguintes extensões para facilitar o desenvolvimento com o NestJS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint" rel="noopener noreferrer"&gt;&lt;strong&gt;ESLint&lt;/strong&gt;&lt;/a&gt;: Extensão para linting de código JavaScript e TypeScript.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode" rel="noopener noreferrer"&gt;&lt;strong&gt;Prettier&lt;/strong&gt;&lt;/a&gt;: Extensão para formatação de código.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=humao.rest-client" rel="noopener noreferrer"&gt;&lt;strong&gt;REST Client&lt;/strong&gt;&lt;/a&gt;: Extensão para fazer requisições HTTP diretamente do VSCode.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Criando sua primeira aplicação com o NestJS
&lt;/h2&gt;

&lt;p&gt;Agora que você tem o NestJS CLI instalado, vamos criar sua primeira aplicação com o NestJS. Para isso, execute o seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nest new nome-do-seu-projeto
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No meu caso, vou criar um projeto chamado &lt;code&gt;nestjs-auth&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nest new nestjs-auth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O NestJS CLI perguntará qual gerenciador de pacotes você deseja usar. Escolha o PNPM e pressione Enter.&lt;br&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%2Fh7w1ps0nn1575lcy66p0.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%2Fh7w1ps0nn1575lcy66p0.png" alt="Criando projeto " width="800" height="507"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ao final do processo, que é bem rápido com o PNPM, você verá uma mensagem informando que o projeto foi criado com sucesso:&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%2Fqjt5zkgb595yfwt9hqb4.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%2Fqjt5zkgb595yfwt9hqb4.png" alt="Projeto criado com sucesso" width="800" height="507"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Após a criação do projeto, entre na pasta do projeto:&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;nestjs-auth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Abra no seu editor de código preferido. Vou usar o Visual Studio Code.&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%2Fy1isrji4u42trzz50nq4.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%2Fy1isrji4u42trzz50nq4.png" alt="Projeto no Visual Studio Code" width="800" height="552"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Estrutura do projeto
&lt;/h2&gt;

&lt;p&gt;A estrutura do projeto criada pelo NestJS CLI é a seguinte:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nestjs-auth/
├── node_modules/
├── src/
│   ├── app.controller.spec.ts
│   ├── app.controller.ts
│   ├── app.module.ts
│   ├── app.service.ts
│   ├── main.ts
├── test/
├── .gitignore
├── .prettierrc
├── eslint.config.mjs
├── nest-cli.json
├── package.json
├── pnpm-lock.yaml
├── README.md
├── tsconfig.build.json
├── tsconfig.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;src/&lt;/code&gt;: Onde fica o código fonte da aplicação:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;app.controller.spec.ts&lt;/code&gt;: Arquivo de teste do controlador raiz da aplicação. Ele é responsável por testar o controlador.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;app.controller.ts&lt;/code&gt;: Controlador raiz da aplicação. Ele é responsável por lidar com as requisições HTTP e retornar as respostas.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;app.module.ts&lt;/code&gt;: Módulo raiz da aplicação. Ele é responsável por importar e configurar os demais módulos, controladores e serviços da aplicação.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;app.service.ts&lt;/code&gt;: Serviço raiz da aplicação. Ele é responsável por conter a lógica de negócios da aplicação.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;main.ts&lt;/code&gt;: Ponto de entrada da aplicação. Ele é responsável por iniciar o servidor e carregar o módulo raiz da aplicação usando o &lt;code&gt;NestFactory&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;test/&lt;/code&gt;: Onde ficam os testes da aplicação, focados em testes de integração e E2E.&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;.gitignore&lt;/code&gt;: Arquivo de configuração do Git. Ele contém os arquivos e pastas que devem ser ignorados pelo Git.&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;.prettierrc&lt;/code&gt;: Arquivo de configuração do Prettier. Ele contém as regras de formatação do código e pode ser JSON ou YAML.&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;eslint.config.mjs&lt;/code&gt;: Arquivo de configuração do ESLint. Ele contém as regras de linting do código.&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;nest-cli.json&lt;/code&gt;: Arquivo de configuração do NestJS CLI. Ele contém as configurações do projeto, como o diretório de saída dos arquivos compilados.&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;package.json&lt;/code&gt;: Arquivo de configuração do projeto. Ele contém as dependências, scripts e configurações do projeto.&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;pnpm-lock.yaml&lt;/code&gt;: Arquivo de bloqueio do PNPM. Ele contém as versões exatas das dependências instaladas no projeto, garantindo que todos os desenvolvedores utilizem as mesmas versões.&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;README.md&lt;/code&gt;: Arquivo de documentação do projeto. Ele contém informações sobre o projeto, como instalar, executar e contribuir.&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;tsconfig.build.json&lt;/code&gt;: Esse arquivo estende o &lt;code&gt;tsconfig.json&lt;/code&gt; e contém as configurações específicas para a construção (build) do projeto. Com isso, ele adiciona ou sobrescreve algumas configurações do tsconfig.json para a construção do projeto&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;tsconfig.json&lt;/code&gt;: Arquivo de configuração do TypeScript. Ele contém as configurações do compilador TypeScript, como o diretório de saída dos arquivos compilados e as opções de compilação.&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Executando a aplicação
&lt;/h2&gt;

&lt;p&gt;O Nest CLI cria o projeto com um &lt;code&gt;AppController&lt;/code&gt; que é responsável por lidar com as requisições HTTP na rota raiz &lt;code&gt;/&lt;/code&gt;. Ele invoca o método &lt;code&gt;getHello()&lt;/code&gt; do serviço &lt;code&gt;AppService&lt;/code&gt;:&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%2Fr24543ofnditv59i6mwm.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%2Fr24543ofnditv59i6mwm.png" alt="Controller criado pelo NestJS CLI" width="800" height="552"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O &lt;code&gt;AppService&lt;/code&gt; possui um método &lt;code&gt;getHello()&lt;/code&gt; que retorna uma string &lt;code&gt;"Hello World!"&lt;/code&gt; que é retornada pelo &lt;code&gt;AppController&lt;/code&gt;:&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%2Fq07fs46xvz4wof292q1h.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%2Fq07fs46xvz4wof292q1h.png" alt="Service criado pelo NestJS CLI" width="800" height="552"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para executar a aplicação, você pode usar o seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm run start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pronto, a aplicação deve estar rodando na porta 3000. Você pode acessar a aplicação no seu navegador através do endereço &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt; ou usar o &lt;a href="https://marketplace.visualstudio.com/items?itemName=humao.rest-client" rel="noopener noreferrer"&gt;&lt;strong&gt;REST Client&lt;/strong&gt;&lt;/a&gt; do VSCode para fazer uma requisição GET para a rota raiz &lt;code&gt;/&lt;/code&gt;. Para isso crie um arquivo &lt;code&gt;api.http&lt;/code&gt; na raiz do projeto com o seguinte conteúdo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET http://localhost:3000/
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E clique no botão &lt;code&gt;Send Request&lt;/code&gt; que aparece acima da requisição. Você deve ver o seguinte resultado:&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%2F49ey6ofj3rm4he6708bs.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%2F49ey6ofj3rm4he6708bs.png" alt="Resultado da requisição GET na rota raiz" width="800" height="483"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Próximos passos
&lt;/h2&gt;

&lt;p&gt;Agora que você já tem sua primeira aplicação rodando, você pode começar a explorar os principais conceitos e funcionalidades do NestJS. Lembre-se de enviar seu projeto para o repositório remoto como o GitHub ou GitLab.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Lembre-se de que vamos utilizar esse projeto ou criar novos projetos durante a série.&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;Neste artigo, você aprendeu o que é o NestJS, por que usá-lo e como criar sua primeira aplicação. Também vimos a estrutura do projeto criado pelo NestJS CLI e como executar a aplicação. Por hoje é só, mas não se preocupe, ainda temos muito mais pela frente!&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>nestjs</category>
      <category>node</category>
      <category>programming</category>
    </item>
    <item>
      <title>Ambiente PHP e Ngnix com Docker</title>
      <dc:creator>Jonilson Sousa</dc:creator>
      <pubDate>Fri, 19 Nov 2021 16:56:38 +0000</pubDate>
      <link>https://dev.to/jonilsonds9/ambiente-php-e-ngnix-com-docker-23ma</link>
      <guid>https://dev.to/jonilsonds9/ambiente-php-e-ngnix-com-docker-23ma</guid>
      <description>&lt;p&gt;Há alguns dias atrás precisei criar ou recriar um ambiente PHP semelhante ao ambiente de produção, em produção era utilizado o PHP na versão 7.2, com o Nginx na versão 1.14.0 e também o PHP-FPM que é o cara responsável por interpretar o código PHP já que o Nginx não consegue fazer isso, mais isso tudo diretamente pelo sistema usando unix sockets, tudo instalado diretamente no sistema. &lt;/p&gt;

&lt;p&gt;Porém tive algumas dificuldades para criar o ambiente usando o fastcgi e então resolvi escrever este artigo para ajudar outras pessoas que venham a precisar e também para o meu eu do futuro que pode vir a precisar fazer algo semelhante.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dockerfile
&lt;/h2&gt;

&lt;p&gt;Bem, primeiro precisamos criar um Dockerfile na raiz do projeto para termos uma imagem com o nosso projeto php, e já com o php-fpm. Podemos ter o Dockerfile o seguinte conteúdo:&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="s"&gt;FROM php:7.2.24-fpm&lt;/span&gt;
&lt;span class="s"&gt;COPY . /var/www/html&lt;/span&gt;
&lt;span class="s"&gt;WORKDIR /var/www/html&lt;/span&gt;
&lt;span class="s"&gt;RUN chmod -R 777 /var/www/html&lt;/span&gt;
&lt;span class="s"&gt;EXPOSE &lt;/span&gt;&lt;span class="m"&gt;9000&lt;/span&gt;
&lt;span class="s"&gt;CMD ["php-fpm"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Explicando o Dockerfile
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;FROM php:7.2.24-fpm&lt;/code&gt;: Com isso vamos ter uma imagem com o php-fpm na versão 7.2.24.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;COPY . /var/www/html&lt;/code&gt;: Aqui fazemos a cópia de todos os arquivos do projeto (&lt;code&gt;.&lt;/code&gt;) para a pasta &lt;code&gt;/var/www/html&lt;/code&gt; do container.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;WORKDIR /var/www/html&lt;/code&gt;: E precisamos mudar o diretório de trabalho para que seja o primeiro e consigamos ter acesso aos arquivos nesse container.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;RUN chmod -R 777 /var/www/html&lt;/code&gt;: Esse comando é para evitar possíveis erros caso o projeto precise criar ou gerenciar arquivos dentro do container.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;EXPOSE 9000&lt;/code&gt;: Aqui liberamos a porta 9000 para podermos acessar de fora, ou no caso em outros conatiners.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;CMD ["php-fpm"]&lt;/code&gt;: Por fim, executamos o php-fpm.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  docker-compose
&lt;/h2&gt;

&lt;p&gt;Agora que temos o Dockerfile, precisamos criar um &lt;code&gt;docker-compose.yml&lt;/code&gt; na raiz do projeto para usarmos o Dockerfile criado anteriormente. E nesse docker-compose temos o seguinte conteúdo:&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;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.7'&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;php&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
      &lt;span class="na"&gt;dockerfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Dockerfile&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dev-site&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./nginx/php-fpm.conf:/etc/php/7.2/fpm/php-fpm.conf&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;site-network&lt;/span&gt;

  &lt;span class="na"&gt;nginx&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx:1.14.0&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dev-nginx&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8001:80"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./nginx/nginx.conf:/etc/nginx/nginx.conf&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./nginx/sites.conf/:/etc/nginx/conf.d/default.conf&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;nginx-debug&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;-g'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;daemon&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;off;'&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;site-network&lt;/span&gt;

&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;site-network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bridge&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Explicando o docker-compose
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;services&lt;/code&gt;: Temos dois serviços, um para o PHP e o outro para o Nginx.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Serviço &lt;code&gt;php&lt;/code&gt;: Nesse bloco fazemos o build na imagem a partir do nosso Dockerfile criado anteriormente. Adicionamos um nome ao container para facilitar a utilização do mesmo. Também fizemos um bind do arquivo de configuração do php-fpm (&lt;code&gt;php-fpm.conf&lt;/code&gt;) para o container. E por fim adicionamos a rede que é criada no bloco &lt;code&gt;networks&lt;/code&gt; que é o último bloco do arquivo para podermos fazer a comunicação entre ambos os containers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Serviço &lt;code&gt;Nginx&lt;/code&gt;: Nesse bloco usamos uma imagem pronta do Nginx na versão 1.14.0 que é a versão que estava sendo executada em produção, também adicionamos um nome para facilitar o uso. E liberamos a porta &lt;code&gt;8001&lt;/code&gt; da máquina para a porta &lt;code&gt;80&lt;/code&gt; do container, isso porque podemos já utilizar a porta 80 da máquina por algum outro motivo. E adicionamos os volumes, na verdade fazemos apenas o bind do &lt;code&gt;nginx.conf&lt;/code&gt; e do &lt;code&gt;sites.conf&lt;/code&gt; que ambos estão dentro da pasta &lt;code&gt;nginx&lt;/code&gt; na raiz do projeto com o &lt;code&gt;/etc/nginx/nginx.conf&lt;/code&gt; e &lt;code&gt;/etc/nginx/conf.d/default.conf&lt;/code&gt; respectivamente. Você pode estar se perguntando sobre esses arquivos, mas calma, ainda vamos ver esses arquivos mais adiante. Também executamos um comando para habilitar o modo de &lt;code&gt;debug&lt;/code&gt; do nginx para podemos ver possíveis problemas quando executarmos o mesmo. E por fim a rede para comunicação com o container PHP.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;networks&lt;/code&gt;: Criamos esse bloco apenas para criar a rede e conseguimos comunicar ambos os containers.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Nginx.conf
&lt;/h2&gt;

&lt;p&gt;Como você deve ter visto anteriormente fazemos o bind da configuração do Nginx, isso porque nossa configuração pode ser diferente da configuração default. Mas nesse ponto mantive quase a mesma configuração do Nginx:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;

load_module modules/ngx_http_image_filter_module.so;

events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    keepalive_timeout  65;

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Não vou entrar muito nessa parte de configuração do Nginx porque penso que foge um pouco do escopo deste artigo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sites
&lt;/h2&gt;

&lt;p&gt;E chegamos a outro ponto importante de toda essa configuração que é a comunicação entre o Nginx e o php-fpm, e essa configuração pode ser feita de duas formas. &lt;/p&gt;

&lt;h3&gt;
  
  
  Proxy reverso
&lt;/h3&gt;

&lt;p&gt;A primeira forma é usando o proxy reverso do Nginx, e para isso utilizamos o &lt;code&gt;proxy_pass&lt;/code&gt; para encaminhar a requisição para o nosso outro container.&lt;/p&gt;

&lt;p&gt;Então naquele arquivo &lt;code&gt;sites.conf&lt;/code&gt; que fizemos o bind para o container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- ./nginx/sites.conf/:/etc/nginx/conf.d/default.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Teríamos o seguinte conteúdo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;upstream container {
    least_conn;
    server dev-site:9000;
}

server {
    listen 80;
    location / {
        proxy_pass http://container;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Explicando: Aqui criamos um &lt;code&gt;upstream&lt;/code&gt; com o nome &lt;code&gt;container&lt;/code&gt;, e esse basicamente aponta para o nosso container, que pode ser acessado usando o nome que criamos lá no docker-compose &lt;code&gt;dev-site&lt;/code&gt; e indicando a porta 9000 que foi a porta que liberamos no container (&lt;code&gt;EXPOSE 9000&lt;/code&gt;). E em seguida, no bloco &lt;code&gt;server&lt;/code&gt; passamos para o proxy_pass o &lt;code&gt;upstream&lt;/code&gt; criado acima porém usando o HTTP, isso porque aqui estamos enviando via HTTP.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fastcgi
&lt;/h3&gt;

&lt;p&gt;A outra forma, e nesse caso a mais interessante é usando o fastcgi que é um protocolo para a comunicação entre o PHP e o Nginx. Também não vou entrar nesse foco aqui. Teremos a seguinte configuração naquele arquivo &lt;code&gt;sites.conf&lt;/code&gt; (no lugar da configuração anterior):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;server {
    listen 80;

    root /var/www/html;

    location / {
        include fastcgi_params;
        fastcgi_pass dev-site:9000;
        fastcgi_param SCRIPT_FILENAME $document_root/index.php;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nesse caso não teremos o &lt;code&gt;upstream&lt;/code&gt;, apenas o bloco &lt;code&gt;server&lt;/code&gt; e os pontos importantes aqui são as linhas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;include fastcgi_params;&lt;/code&gt;: que inclui os outros parâmetros, que ficam no arquivo &lt;code&gt;fastcgi_params&lt;/code&gt; dentro dos arquivos de configuração do Nginx.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;fastcgi_pass dev-site:9000;&lt;/code&gt;: Essa linhas é responsável pelo direcionamento das requisições para o php-fpm, por isso indicamos o nome e a porta do nosso container do php &lt;code&gt;dev-site:9000&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;fastcgi_param SCRIPT_FILENAME $document_root/index.php;&lt;/code&gt;: E aqui indicamos qual o arquivo deve ser executado no container do php.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Agora é só subir os containers usando o comando &lt;code&gt;docker-compose up&lt;/code&gt; estando dentro da pasta do projeto e logo em seguida acessar o endereço &lt;a href="http://localhost:8001"&gt;http://localhost:8001&lt;/a&gt; no navegador.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>php</category>
      <category>nginx</category>
      <category>devops</category>
    </item>
    <item>
      <title>Anotações Capítulo 9: Unit Tests</title>
      <dc:creator>Jonilson Sousa</dc:creator>
      <pubDate>Mon, 26 Jul 2021 17:34:10 +0000</pubDate>
      <link>https://dev.to/jonilsonds9/anotacoes-capitulo-9-unit-tests-4efh</link>
      <guid>https://dev.to/jonilsonds9/anotacoes-capitulo-9-unit-tests-4efh</guid>
      <description>&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Antigamente os testes era um programa simples de controle que interagia manualmente com o programa escrito.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Exemplo: Um simples programa de controle que esperava alguma ação no teclado. Ele só iria agendar um o caractere digitado para reproduzir 5 segundos depois. Então digitava uma melodia no teclado e esperava que fosse reproduzida na tela depois. Esse era o teste.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Geralmente o código de teste era jogado fora.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mas atualmente deveríamos criar um teste que garantisse que cada canto do código funcionasse como esperamos.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Isolarmos o código do resto do sistema operacional em vez de invocar as funções padrões de contagem.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Simularmos aquelas funções de modo que tivéssemos o controle absoluto sobre o tempo. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Agendaremos comandos que configuraram flags booleanas; Adiantamos o tempo, observando as flags e verificando se elas mudam de falsas para verdadeiras quando colocamos o valor correto no tempo.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;E para passar uma coleção de testes adiante, precisamos nos certificar se eles são adequados para serem executados por qualquer pessoa e se eles e o código estão juntos no mesmo pacote.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Progredimos bastante ao longo do tempo, com os movimentos Agile e TDD. Porém muitos programadores têm se esquecido de alguns dos pontos mais sutis e importantes de escrever bons testes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  As três leis do TDD
&lt;/h2&gt;

&lt;p&gt;Sabemos que o TDD nos pede para criar primeiro os testes e depois o código de produção. Mas isso é apenas o início. Considere as três leis abaixo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Primeira Lei&lt;/strong&gt;: Não se deve escrever o código de produção até criar um teste de unidade de falhas.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Segunda Lei&lt;/strong&gt;: Não se deve escrever mais de um teste de unidade do que o necessário para falhar, e não compilar é falhar.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Terceira Lei&lt;/strong&gt;: Não se deve escrever mais códigos de produção do que o necessário para aplicar o teste de falha atual.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Os testes e o código de produção são escritos juntos, com os testes apenas alguns segundos mais adiantados.&lt;/p&gt;

&lt;p&gt;Dessa forma teríamos milhares de testes, e os mesmos cobririam praticamente todo o nosso código de produção. Assim o tamanho completo dos testes, pode competir com o tamanho do próprio código de produção, o que pode apresentar um problema de gerenciamento intimidador.&lt;/p&gt;

&lt;h2&gt;
  
  
  Como manter os testes limpos
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Testes feitos “porcamente” é o equivalente, se não pior, a não ter teste algum&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Já que muitos testes devem ser alterados conforme o código de produção evolui.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Quanto pior o teste, mais difícil é mudá-lo.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Quanto mais confuso o teste, maiores as chances de levar mais tempo escrevendo novos testes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;E conforme o código de produção é alterado, os testes antigos começam a falhar e a bagunça nos testes dificulta fazê-los funcionar novamente. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Assim, os testes passam a ser vistos como um problema em constante crescimento.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Com tudo, a manutenção dos testes pode contribuir negativamente para a finalização do projeto. E no final podemos ser forçados a descartar todos os testes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Porém sem os testes, não podemos garantir que, após as alterações no código, ele funcionasse como o esperado e que mudanças em uma parte do sistema não afetam outras partes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Com isso, os bugs crescem, e o medo de alterar o código fica maior. E com isso o código de produção começa a se degradar.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No fim de tudo, ficamos sem testes, com um código de produção confuso e cheio de bugs, com consumidores frustrados e o esforço para criação de testes não valeu de nada.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tudo isso é fato, porém se tivéssemos mantidos os testes limpos, o esforço para a criação dos testes não teria sido em vão.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Assim: &lt;strong&gt;os código de testes são tão importantes quanto o código de produção&lt;/strong&gt;. Ele não é secundário, ele requer raciocínio, planejamento e cuidado. É Preciso mantê-lo tão limpo quanto o código de produção.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Os testes habilitam as “-idades”
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Se não mantiver seus testes limpos, irá perdê-los&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;E sem eles, perdemos exatamente o que mantém a flexibilidade no código de produção.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;São os testes de unidade que mantêm seus códigos flexíveis, reutilizáveis e passíveis de manutenção. Isso porque se tiver testes, não terá medo de alterar o código!&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Quanto maior a cobertura de seus testes, menor o medo. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Portanto, ter uma coleção de testes de unidade automatizados que cubram o código de produção é o segredo para manter seu projeto e arquitetura o mais limpos possíveis.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Os testes habilitam todas as “-idades”, pois eles possibilitam as alterações.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Do contrário, se seus testes forem ruins, sua capacidade de modificar seu código fica comprometida e perde a capacidade de alterá-lo. No fim, você perde os testes e seu código se degrada.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Testes limpos
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;O que torna um teste limpo? Três coisas: Legibilidade, legibilidade e legibilidade&lt;/strong&gt;. Talvez isso seja até mais importante nos testes de unidade do que no código de produção.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;O que torna os testes legíveis? O mesmo que torna os códigos legíveis: Clareza, simplicidade, consistência de expressão.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Considere o código do FitNesse:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public void testGetPageHierarchyAsXml() throws Exception {
    crawler.addPage(root, PathParser.parse("PageOne"));
    crawler.addPage(root,       PathParser.parse("PageOne.ChildOne"));
    crawler.addPage(root, PathParser.parse("PageTwo"));

    request.setResource("root");
    request.addInput("type", "pages");
    Responder responder = new SerializedPageResponder();
    SimpleResponse response = (SimpleResponse) responder.makeResponse(new FitNesseContext(root), request);
    String xml = response.getContent();

    assertEquals("text/xml", response.getContentType());
    assertSubString("&amp;lt;name&amp;gt;PageOne&amp;lt;/name&amp;gt;", xml);
    assertSubString("&amp;lt;name&amp;gt;PageTwo&amp;lt;/name&amp;gt;", xml);
    assertSubString("&amp;lt;name&amp;gt;ChildOne&amp;lt;/name&amp;gt;", xml);
}

public void testGetPageHierarchyAsXmlDoesntContainSymbolicLinks() throws Exception {
    WikiPage pageOne = crawler.addPage(root, PathParser.parse("PageOne"));
    crawler.addPage(root,    PathParser.parse("PageOne.ChildOne"));
    crawler.addPage(root, PathParser.parse("PageTwo"));

    PageData data = pageOne.getData();
    WikiPageProperties properties = data.getProperties();
    WikiPageProperty symLinks = properties.set(SymbolicPage.PROPERTY_NAME);
    symLinks.set("SymPage", "PageTwo");
    pageOne.commit(data);

    request.setResource("root");
    request.addInput("type", "pages");
    Responder responder = new SerializedPageResponder();
    SimpleResponse response = (SimpleResponse) responder.makeResponse(new FitNesseContext(root), request);
    String xml = response.getContent();

    assertEquals("text/xml", response.getContentType());
    assertSubString("&amp;lt;name&amp;gt;PageOne&amp;lt;/name&amp;gt;", xml);
    assertSubString("&amp;lt;name&amp;gt;PageTwo&amp;lt;/name&amp;gt;", xml);
    assertSubString("&amp;lt;name&amp;gt;ChildOne&amp;lt;/name&amp;gt;", xml);
    assertNotSubString("SymPage", xml);
}

public void testGetDataAsHtml() throws Exception {
    crawler.addPage(root, PathParser.parse("TestPageOne"), "test page");
    request.setResource("TestPageOne");
    request.addInput("type", "data");

    Responder responder = new SerializedPageResponder();
    SimpleResponse response = (SimpleResponse)     responder.makeResponse(new FitNesseContext(root), request);
    String xml = response.getContent();

    assertEquals("text/xml", response.getContentType());
    assertSubString("test page", xml);
    assertSubString("&amp;lt;Test", xml);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Veja as chamadas para &lt;code&gt;PathParser&lt;/code&gt;. Elas transformam strings em instâncias &lt;code&gt;PagePath&lt;/code&gt; pelos &lt;code&gt;crawler&lt;/code&gt;. Essa transformação é irrelevante na execução do teste e serve apenas para ofuscar o objetivo. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Os detalhes em torno da criação do responder e a definição do tipo de &lt;code&gt;response&lt;/code&gt; também são apenas aglomerados. E em nada interferem na forma pela qual é construído a URL requisitada a partir de um &lt;code&gt;resource&lt;/code&gt; e um parâmetro.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No final, &lt;strong&gt;esse código não foi feito para ser lido&lt;/strong&gt;. Tem muitos detalhes para serem entendidos antes. Agora considere os mesmos testes refatorados:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public void testGetPageHierarchyAsXml() throws Exception {
    makePages("PageOne", "PageOne.ChildOne", "PageTwo");
    submitRequest("root", "type:pages");
    assertResponseIsXML();
    assertResponseContains("&amp;lt;name&amp;gt;PageOne&amp;lt;/name&amp;gt;", "&amp;lt;name&amp;gt;PageTwo&amp;lt;/name&amp;gt;", "&amp;lt;name&amp;gt;ChildOne&amp;lt;/name&amp;gt;");
}

public void testSymbolicLinksAreNotInXmlPageHierarchy() throws Exception {
    WikiPage page = makePage("PageOne");
    makePages("PageOne.ChildOne", "PageTwo");

    addLinkTo(page, "PageTwo", "SymPage");

    submitRequest("root", "type:pages");

    assertResponseIsXML();
    assertResponseContains( "&amp;lt;name&amp;gt;PageOne&amp;lt;/name&amp;gt;", "&amp;lt;name&amp;gt;PageTwo&amp;lt;/name&amp;gt;", "&amp;lt;name&amp;gt;ChildOne&amp;lt;/name&amp;gt;");
    assertResponseDoesNotContain("SymPage");
}

public void testGetDataAsXml() throws Exception {
    makePageWithContent("TestPageOne", "test page");

    submitRequest("TestPageOne", "type:data");

    assertResponseIsXML();
    assertResponseContains("test page", "&amp;lt;Test");
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A estrutura tornou óbvio o padrão CONSTRUIR-OPERAR-VERIFICAR.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cada teste está dividido em três partes: Primeira produzir os dados do teste, segunda operar sobre eles, terceira verifica os resultados gerados.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;E a grande maioria dos dados desnecessários foi eliminada.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Os testes vão direto ao ponto e usam apenas os tipos de dados e funções que realmente precisam.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Assim quem ler pode rapidamente descobrir o que eles fazem. Sem ser prejudicado pelos detalhes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Linguagem de testes específica do domínio
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;O exemplo anterior mostra a técnica da construção de uma linguagem específica a um domínio.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Em vez de usar as APIs que os programadores utilizam para manipular o sistema, construímos uma série de funções e utilitários, que tornam os testes mais fáceis de escrever e ler.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Assim, desenvolvedores disciplinados também refatoram seus códigos de teste para formas mais sucintas e expressivas.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Um padrão duplo
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Os códigos de testes são totalmente diferentes do código de produção. Ele pode ser simples, sucinto, expressivo, mas não precisa ser mais eficiente do que o código de produção.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ele roda num ambiente de teste, e não de um de produção, e esses dois ambientes possuem requisitos diferentes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Considere o código abaixo, sem entrar em detalhes posso lhe dizer que o teste verifica se o alarme de temperatura baixa, o aquecedor e o ventilador estão todos ligados quando a temperatura estiver “fria demais”:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Test
public void turnOnLoTempAlarmAtThreashold() throws Exception {
    hw.setTemp(WAY_TOO_COLD);
    controller.tic();
    assertTrue(hw.heaterState());
    assertTrue(hw.blowerState());
    assertFalse(hw.coolerState());
    assertFalse(hw.hiTempAlarm());
    assertTrue(hw.loTempAlarm());
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Sem se preocupar com os detalhes, apenas focando no estado final do sistema quando a temperatura é “fria demais”.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;E notamos que sempre precisamos ver o que está sendo verificado e voltarmos para a esquerda para esquerda para ver se é &lt;code&gt;assertTrue&lt;/code&gt; ou &lt;code&gt;assertFalse&lt;/code&gt;. Isso é falível, além de dificultar a leitura do teste.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Agora vejamos a refatoração do teste aperfeiçoando a legibilidade:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Test
public void turnOnLoTempAlarmAtThreshold() throws Exception {
    wayTooCold();
    assertEquals("HBchL", hw.getState());
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Foi criado uma função &lt;code&gt;wayTooCold()&lt;/code&gt; para ocultar o detalhe da função &lt;code&gt;tic&lt;/code&gt;. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mas o estranho é a string em &lt;code&gt;assertEquals&lt;/code&gt;. As letras maiúsculas significam “ligado” e as minúsculas “desligado”, e elas sempre seguem a ordem: &lt;code&gt;{heater, blower, cooler, hi-temp-alarm, lo-temp-alarm}&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;“Mesmo que esse código esteja perto de violar a regra de mapeamento mental, neste caso parece apropriado”.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Assim, conhecendo o significado da string, logo conseguimos interpretar os resultados. Assim, veja a listagem de testes:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Test
public void turnOnCoolerAndBlowerIfTooHot() throws Exception {
    tooHot();
    assertEquals("hBChl", hw.getState());
}

@Test
public void turnOnHeaterAndBlowerIfTooCold() throws Exception {
    tooCold();
    assertEquals("HBchl", hw.getState());
}

@Test
public void turnOnHiTempAlarmAtThreshold() throws Exception {
    wayTooHot();
    assertEquals("hBCHl", hw.getState());
}

@Test
public void turnOnLoTempAlarmAtThreshold() throws Exception {
    wayTooCold();
    assertEquals("HBchL", hw.getState());
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Agora veja o código da função &lt;code&gt;getState()&lt;/code&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public String getState() {
    String state = "";
    state += heater ? "H" : "h";
    state += blower ? "B" : "b";
    state += cooler ? "C" : "c";
    state += hiTempAlarm ? "H" : "h";
    state += loTempAlarm ? "L" : "l";
    return state;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esse código não é muito eficiente. Para isso deveria ser usado o &lt;code&gt;StringBuffer&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;As &lt;code&gt;StringBuffer&lt;/code&gt; são um pouco feias. Mas evitamos usar no código de produção se o custo for pequeno.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Contudo, esse aplicativo é um sistema em tempo real, e é provável que os recursos sejam limitados. Entretanto, o ambiente de testes não costuma ter limitação.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;“Essa é a natureza do padrão duplo. Há coisas que você talvez jamais faça num ambiente de produção que esteja perfeitamente bem em um ambiente de teste. Geralmente, isso envolve questões de eficiência de memória e da CPU. Mas nunca de clareza.”&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Uma afirmação por teste
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Há uma escola de pensamento que diz que cada teste em JUnit deve ter uma e apenas uma instrução de afirmação (assert). Essa regra pode parecer perversa, mas a vantagem pode ser vista no exemplo da listagem de testes do aplicativo em tempo real, cujo os testes chegam a uma única conclusão que é fácil e rápida de entender.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mas na listagem dos testes de URL, parece ilógico que poderíamos de alguma forma adicionar afirmação se a saída está em XML e se ela contém certas&lt;code&gt;substrings&lt;/code&gt;. Para resolver isso poderíamos dividir o teste em dois, cada um com sua afirmação:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public void testGetPageHierarchyAsXml() throws Exception {
    givenPages("PageOne", "PageOne.ChildOne", "PageTwo");
    whenRequestIsIssued("root", "type:pages");
    thenResponseShouldBeXML();
}

public void testGetPageHierarchyHasRightTags() throws Exception {
    givenPages("PageOne", "PageOne.ChildOne", "PageTwo");
    whenRequestIsIssued("root", "type:pages");
    thenResponseShouldContain("&amp;lt;name&amp;gt;PageOne&amp;lt;/name&amp;gt;", "&amp;lt;name&amp;gt;PageTwo&amp;lt;/name&amp;gt;", "&amp;lt;name&amp;gt;ChildOne&amp;lt;/name&amp;gt;");
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Note que os nomes das funções para usar a convenção comum &lt;strong&gt;dado-quando-então&lt;/strong&gt;. Isso facilita ainda mais a leitura dos testes. Infelizmente, dividir os testes pode gerar muito código duplicado.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Podemos usar o padrão Template Method para eliminar a duplicação e colocar as partes &lt;em&gt;dado/quando&lt;/em&gt; na classe base e as partes então em derivadas diferentes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ou poderíamos criar uma classe de teste completamente separada e colocar as partes &lt;em&gt;dado e quando&lt;/em&gt; na função &lt;code&gt;@Before&lt;/code&gt; e as partes &lt;em&gt;quando&lt;/em&gt; em cada função &lt;code&gt;@Test&lt;/code&gt;. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mas em ambos os casos parece muito trabalho, no fim é preferível usar múltiplas afirmações&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A regra da afirmação única é uma boa orientação. E geralmente podemos tentar criar uma linguagem de teste para um domínio específico que a use. Mas não tem problema em colocar mais de uma afirmação em um teste.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Um único conceito por teste
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Talvez a melhor regra seja que desejamos um único conceito em cada função de teste.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Não queremos funções longas que saiam testando várias coisas uma após a outra.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No exemplo abaixo o teste é longo e sai testando várias coisas. Ele deveria ser dividido em três:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
* Miscellaneous tests for the addMonths() method.
*/
public void testAddMonths() {
    SerialDate d1 = SerialDate.createInstance(31, 5, 2004);

    SerialDate d2 = SerialDate.addMonths(1, d1);
    assertEquals(30, d2.getDayOfMonth());
    assertEquals(6, d2.getMonth());
    assertEquals(2004, d2.getYYYY());

    SerialDate d3 = SerialDate.addMonths(2, d1);
    assertEquals(31, d3.getDayOfMonth());
    assertEquals(7, d3.getMonth());
    assertEquals(2004, d3.getYYYY());

    SerialDate d4 = SerialDate.addMonths(1,        SerialDate.addMonths(1, d1));
    assertEquals(30, d4.getDayOfMonth());
    assertEquals(7, d4.getMonth());
    assertEquals(2004, d4.getYYYY());
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;As funções de teste devem ser:

&lt;ul&gt;
&lt;li&gt;Dado o último dia de um mês com 31 dias (como maio):&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Quando você adicionar um mês cujo último dia seja 30 (como junho), então deverá ser o dia 30 daquele mês, e não o 31.&lt;/li&gt;
&lt;li&gt;Quando você adicionar dois meses aquela data cujo último dia seja 31, então a data deverá ser o dia 31.&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Dado o último dia de um mês com 30 dias (como junho):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Quando você adicionar um mês cujo último dia seja 31, então a data deverá ser dia 30 e não 31.&lt;/li&gt;
&lt;li&gt;Ainda está faltando o teste que verifica que ao incrementar o mês, a data não pode ser maior do que o último dia daqueles mês.&lt;/li&gt;
&lt;li&gt;Assim, as múltiplas afirmações não são problema e sim os conceitos, que nesse caso é mais de um.&lt;/li&gt;
&lt;li&gt;Assim, é melhor minimizar o número de afirmações por conceito e testar apenas um conceito por teste.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  F.I.R.S.T
&lt;/h2&gt;

&lt;p&gt;Testes limpos seguem outras cinco regras:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Rapidez (Fast)&lt;/strong&gt;: Os testes devem ser rápidos.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Independência (Independent)&lt;/strong&gt;: Os testes não devem depender uns dos outros.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Repetitividade (Repeatable)&lt;/strong&gt;: Deve-se poder repetir os testes em qualquer ambiente.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Autoavaliação (Self-Validating)&lt;/strong&gt;: Os testes devem ter uma saída booleana. Obtenham ou não êxito, você não deve ler um arquivo de registro para saber o resultado.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pontualidade (Timely)&lt;/strong&gt;: Os testes precisam ser escritos em tempo hábil. Devem-se criar os testes de unidade imediatamente antes do código de produção no qual serão aplicados.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Este é só o início deste tópico.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deveria ter um livro inteiro sobre &lt;em&gt;testes limpos&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Os testes são tão importantes para a saúde de um projeto quanto o código de produção&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Talvez até mais, pois eles preservam e aumentam a flexibilidade, capacidade de manutenção e reutilização do código de produção.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mantenha seus testes sempre limpos&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Se deixar os testes se degradarem, seu código também irá. Mantenha limpos seus testes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>books</category>
      <category>codequality</category>
    </item>
    <item>
      <title>Anotações Capítulo 8: Boundaries</title>
      <dc:creator>Jonilson Sousa</dc:creator>
      <pubDate>Mon, 12 Jul 2021 17:03:45 +0000</pubDate>
      <link>https://dev.to/jonilsonds9/anotacoes-capitulo-8-boundaries-3739</link>
      <guid>https://dev.to/jonilsonds9/anotacoes-capitulo-8-boundaries-3739</guid>
      <description>&lt;ul&gt;
&lt;li&gt;Sempre precisamos utilizar módulos, códigos fornecidos por terceiros.&lt;/li&gt;
&lt;li&gt;E devemos integrar de forma limpa esse código externo ao nosso.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  O uso de códigos de terceiros
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Há uma tensão natural entre o fornecedor de uma interface e seu usuário.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Os fornecedores de pacotes (aqui no sentido de módulos) e frameworks de outros fabricantes visam a uma maior aplicabilidade de modo que possam trabalhar com diversos ambientes e atender a um público maior.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Já os usuários desejam uma interface voltada para suas próprias necessidades.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Essa tensão pode causar problemas nos limites de nossos sistemas&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Exemplo: &lt;code&gt;java.util.Map&lt;/code&gt;, é uma interface bastante ampla com diversas capacidades. O que nos dá flexibilidade, isso é útil, mas também pode ser uma desvantagem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nosso aplicativo pode construir um &lt;code&gt;Map&lt;/code&gt; e passá-lo adiante.&lt;/li&gt;
&lt;li&gt;E nosso objetivo talvez seja que nenhum dos recipientes de nosso &lt;code&gt;Map&lt;/code&gt; não exclua nada do &lt;code&gt;Map&lt;/code&gt;. Mas logo no início da lista dos métodos do &lt;code&gt;Map&lt;/code&gt; está o método &lt;code&gt;clear()&lt;/code&gt;. E assim qualquer usuário do &lt;code&gt;Map&lt;/code&gt; pode apagá-lo.&lt;/li&gt;
&lt;li&gt;Ou talvez, segundo a convenção que adotamos, o &lt;code&gt;Map&lt;/code&gt; pode armazenar apenas certos tipos de objetos, mas ele não restringe os tipos que podemos armazenar, assim qualquer usuário pode adicionar itens de qualquer tipo.&lt;/li&gt;
&lt;li&gt;Exemplo &lt;code&gt;sensors&lt;/code&gt;:
Se temos um &lt;code&gt;Map&lt;/code&gt; de &lt;code&gt;sensors&lt;/code&gt; da seguinte forma:
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Map sensors = new HashMap();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E quando alguma parte do código precisar acessar o Sensor, terá que fazer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Sensor s = (Sensor) sensors.get(sensorId);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E isso aparece várias vezes ao longo do código. E com isso o cliente fica com a responsabilidade de obter um &lt;code&gt;Object&lt;/code&gt; do &lt;code&gt;Map&lt;/code&gt; e atribuí-lo ao tipo certo. &lt;strong&gt;Apesar de funcionar, não é um código limpo&lt;/strong&gt;. E esse código não explica muito bem o que ele faz. &lt;br&gt;
E poderíamos melhorar a legibilidade com o uso de tipos genéricos, como:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Map&amp;lt;Sensor&amp;gt; sensors = new HashMap&amp;lt;Sensor&amp;gt;();
…
Sensor s = sensors.get(sensorId );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Observação: O &lt;code&gt;Map&lt;/code&gt; deveria ter a chave e o tipo do valor.&lt;/p&gt;

&lt;p&gt;Porém, isso ainda não resolve o problema de que o &lt;code&gt;Map&amp;lt;Sensor&amp;gt;&lt;/code&gt; oferece mais capacidade do que precisamos ou queremos.&lt;br&gt;
&lt;strong&gt;Passar adiante pelo sistema uma instância de &lt;code&gt;Map&amp;lt;Sensor&amp;gt;&lt;/code&gt; significa que haverá vários lugares para mexer se a interface &lt;code&gt;Map&lt;/code&gt; mudar.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Uma forma limpa de usar o &lt;code&gt;Map&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Sensors {
    private Map sensors = new HashMap();

    public Sensor getById(String id) {
        return (Sensor) sensors.get(id);
    }

    //snip
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dessa forma a interface no limite (Map) está oculta, e é possível alterá-la causando muito pouco impacto no resto do aplicativo. Essa classe também pode forçar regras de modelo e de negócios.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Não estamos sugerindo para sempre usar dessa forma.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mas é bom &lt;strong&gt;não passar os &lt;code&gt;Maps&lt;/code&gt; ou qualquer outra interface num limite&lt;/strong&gt; por todo o sistema.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Se for usar, mantenha numa classe ou próxima a uma família de classes em que ela possa ser usada. &lt;strong&gt;Evite retorná-la ou aceitá-la como parâmetro de APIs públicas&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Explorando e aprendendo sobre limites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Códigos de terceiros nos ajudam a obter mais funcionalidade em menos tempo.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Não é tarefa nossa testá-los, mas pode ser melhor para nós criar testes para os códigos externos que formos usar.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Isso quando não é claro como usar uma biblioteca de terceiros. Podemos gastar um tempo lendo a documentação e decidindo como usá-la. E então escreveremos nosso código para usar o código externo e vemos que não é o que achávamos. E poderíamos passar muito tempo depurando o código e tentando saber se o bug é no nosso código ou no deles.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Entender códigos de terceiros é difícil. Integrá-lo ao seu também é&lt;/strong&gt;. Fazer ambos ao mesmo tempo dobra a dificuldade, e se adotássemos outra abordagem?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Se criarmos testes para explorar nosso conhecimento sobre ele. O que o Jim Newkirk chama isso de &lt;em&gt;testes de aprendizagem&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nesses testes, chamamos a API do código externo como faríamos ao usá-la em nosso aplicativo. Assim estaríamos controlando os experimentos que verificam nosso conhecimento daquela API. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;O teste foca no que desejamos saber sobre a API.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Aprendendo sobre log4j
&lt;/h2&gt;

&lt;p&gt;Para usar o pacote &lt;code&gt;log4j&lt;/code&gt; do Apache, baixaremos o pacote e abriremos a documentação inicial.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sem ler muito, criamos nosso primeiro teste:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Test
public void testLogCreate() {
    Logger logger = Logger.getLogger("MyLogger");
    logger.info("hello");
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Quando executamos, temos um erro dizendo que precisamos de algo chamado &lt;code&gt;Appender&lt;/code&gt;. Após ler um pouco mais, descobrimos o &lt;code&gt;ConsoleAppender&lt;/code&gt;. Então criamos o &lt;code&gt;ConsoleAppender&lt;/code&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Test
public void testLogAddAppender() {
    Logger logger = Logger.getLogger("MyLogger");
    ConsoleAppender appender = new ConsoleAppender();
    logger.addAppender(appender);
    logger.info("hello");
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Agora descobrimos que o &lt;code&gt;Appender&lt;/code&gt; não possui fluxo de saída. Depois de pesquisar tentamos o seguinte:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Test
public void testLogAddAppender() {
    Logger logger = Logger.getLogger("MyLogger");
    logger.removeAllAppenders();
    logger.addAppender(new ConsoleAppender(
    new PatternLayout("%p %t %m%n"), ConsoleAppender.SYSTEM_OUT));
    logger.info("hello");
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;E funcionou. Uma mensagem “hello” apareceu no console! Porém:
Parece estranho ter que dizer ao &lt;code&gt;ConsoleAppender&lt;/code&gt; o que ele precisa escrever no console, e mais interessante é quando removemos o parâmetro &lt;code&gt;ConsoleAppender.SYSTEM_OUT&lt;/code&gt; e ainda é exibido “hello”. Mas quando retiramos o &lt;code&gt;PatternLayout&lt;/code&gt; temos a mensagem de falta de fluxo de saída.
Lendo a documentação novamente, vimos que o construtor &lt;code&gt;ConsoleAppender&lt;/code&gt; padrão vem “desconfigurado”, o que não parece óbvio ou prático. Parece um bug. Lendo mais detalhadamente sobre o pacote chegamos a seguinte série de testes de unidade:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class LogTest {
    private Logger logger;

    @Before
    public void initialize() {
        logger = Logger.getLogger("logger");
        logger.removeAllAppenders();
        Logger.getRootLogger().removeAllAppenders();
    }

    @Test
    public void basicLogger() {
        BasicConfigurator.configure();
        logger.info("basicLogger");
    }

    @Test
    public void addAppenderWithStream() {
        logger.addAppender(new ConsoleAppender(new PatternLayout("%p %t %m%n"), ConsoleAppender.SYSTEM_OUT));
        logger.info("addAppenderWithStream");
    }

    @Test
    public void addAppenderWithoutStream() {
        logger.addAppender(new ConsoleAppender(new PatternLayout("%p %t %m%n")));
        logger.info("addAppenderWithoutStream");
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora sabemos como obter um console simples e inicializado de logs, com isso podemos encapsular essa lógica nas classes de logs para que o resto do código fique isolado da interface limite do &lt;code&gt;log4j&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Os testes de aprendizagem são melhores que de graça
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Esses testes acabam não custando nada. Porque tivemos que aprender sobre a API mesmo, e escrever eles foi uma forma fácil de aprender.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;“Os testes de aprendizagem são experimentos precisos que ajudam a aumentar nosso entendimento”&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Esses testes também geram um retorno positivo. Quando houver novas versões daquele pacote, podemos executar os testes para ver se há diferenças nas atividades&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cada distribuição vem com um novo risco. Porém com os testes de aprendizagem podemos saber se o pacote ficou incompatível com os testes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Também pode ser mais fácil a atualização com os testes, assim podemos ir para novas versões sem grandes problemas desde que os testes continuem passando.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  O uso de código que não existe ainda
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Outro tipo de limite, que separa o conhecido do desconhecido.&lt;/li&gt;
&lt;li&gt;Às vezes, o que está do outro lado nos é desconhecido. Às vezes, optamos por não olhar além do limite.&lt;/li&gt;
&lt;li&gt;Pense num caso onde você vai ter que utilizar uma API externa mas que você não conhece ela e não sabe como ela funciona:

&lt;ul&gt;
&lt;li&gt;Digamos que você usará um subsistema chamado “Transmissor”.&lt;/li&gt;
&lt;li&gt;Nesse caso a melhor abordagem é criar nossa própria interface “Transmitter” que será responsável por se comunicar com o subsistema "Transmissor".&lt;/li&gt;
&lt;li&gt;Nela podemos criar um método “transmit” que pega a frequência e o fluxo de dados. Nesse caso, essa é a interface que gostaríamos que o subsistema "Transmissor" tivesse, que não sabemos como realmente é a sua interface.&lt;/li&gt;
&lt;li&gt;Assim deixamos o código do nosso lado organizado e centralizado.&lt;/li&gt;
&lt;li&gt;E podemos até utilizar testes com um “Transmissor fake” para testarmos o funcionamento do nosso lado.&lt;/li&gt;
&lt;li&gt;Bem como usar “Adapter Transmitter” para fazer a comunicação no futuro com a API externa.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Limites limpos
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Coisas interessantes ocorrem nos limites. A alteração é uma delas.&lt;/li&gt;
&lt;li&gt;Bons projetos de software acomodam modificações sem muito investimento ou trabalho.&lt;/li&gt;
&lt;li&gt;Quando usamos códigos que estão fora de controle, devemos dar uma atenção ao nosso investimento e garantir que uma mudança futura não seja muito custosa.&lt;/li&gt;
&lt;li&gt;O código nos limites precisa de uma divisão clara e testes que definem o que se deve esperar.
Evitar que grande parte do nosso código enxergue as particularidades de terceiros.&lt;/li&gt;
&lt;li&gt;Melhor depender de algo que você controle do que pegar algo que acabe controlando você.&lt;/li&gt;
&lt;li&gt;Lidamos com os limites de códigos externos através de alguns poucos lugares em nosso código que fazem referência a eles.&lt;/li&gt;
&lt;li&gt;Podemos usar uma interface, ou um adapter para converter nossa interface perfeita na que nos for fornecida.&lt;/li&gt;
&lt;li&gt;Nosso código se comunica melhor conosco, provê uso consistente interno e possui poucos pontos para serem mexidos quando o código externo mudar.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>books</category>
      <category>codequality</category>
    </item>
    <item>
      <title>Anotações Capítulo 7: Error Handling</title>
      <dc:creator>Jonilson Sousa</dc:creator>
      <pubDate>Mon, 28 Jun 2021 14:38:08 +0000</pubDate>
      <link>https://dev.to/jonilsonds9/anotacoes-capitulo-7-error-handling-3bf9</link>
      <guid>https://dev.to/jonilsonds9/anotacoes-capitulo-7-error-handling-3bf9</guid>
      <description>&lt;ul&gt;
&lt;li&gt;As coisas podem dar errado, e quando isso ocorre, nós somos responsáveis por certificar que nosso código faça o que seja preciso fazer.&lt;/li&gt;
&lt;li&gt;É quase impossível ver o que o código faz devido a tantos tratamentos de erros.&lt;/li&gt;
&lt;li&gt;Esse recurso é importante, “mas se obscurecer a lógica, está errado”.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Use exceções em vez de retornar códigos
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Antigamente muitas linguagens não suportavam exceções.&lt;/li&gt;
&lt;li&gt;Assim a solução era criar uma flag de erro ou retornar um código de erro que o chamador pudesse verificar. Exemplo:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class DeviceController {
    …
    public void sendShutDown() {
        DeviceHandle handle = getHandle(DEV1);
        // Check the state of the device
        if (handle != DeviceHandle.INVALID) {
            // Save the device status to the record field
            retrieveDeviceRecord(handle);
            // If not suspended, shut down
            if (record.getStatus() != DEVICE_SUSPENDED) {
                pauseDevice(handle);
                clearDeviceWorkQueue(handle);
                closeDevice(handle);
            } else {
                logger.log("Device suspended. Unable to     shut down");
            }
        } else {
            logger.log("Invalid handle for: " +     DEV1.toString());
        }
    }
...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;“O problema era que essas técnicas entupiam o chamador, que devia verificar erros imediatamente após a chamada”&lt;/strong&gt;. Porém facilmente se esqueciam de fazer essa verificação. Por esse motivo, &lt;strong&gt;é melhor lançar uma exceção quando um erro for encontrado&lt;/strong&gt;. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assim o código de chamada fica mais limpo e sua lógica não fica ofuscada pelo tratamento de erro&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Exemplo anterior lançando exceções:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class DeviceController {
    …
    public void sendShutDown() {
        try {
            tryToShutDown();
        } catch (DeviceShutDownError e) {
            logger.log(e);
        }
    }

    private void tryToShutDown() throws DeviceShutDownError {
        DeviceHandle handle = getHandle(DEV1);
        DeviceRecord record = retrieveDeviceRecord(handle);

        pauseDevice(handle);
        clearDeviceWorkQueue(handle);
        closeDevice(handle);
    }

    private DeviceHandle getHandle(DeviceID id) {
        …
        throw new DeviceShutDownError("Invalid handle for: " + id.toString());
        …
    }

    ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;O código fica mais claro. O código fica melhor porque as duas coisas estão separadas: O algoritmo para o desligamento do dispositivo e o tratamento de erro.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Crie primeiro sua estrutura try-catch-finally
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;As exceções definem um escopo dentro de seu programa.
Sempre que executar o &lt;code&gt;try&lt;/code&gt;, você declara que aquela execução pode ser cancelada a qualquer momento e então continuar no catch.&lt;/li&gt;
&lt;li&gt;De certa forma, os blocos &lt;code&gt;try&lt;/code&gt; são como transações. Seu &lt;code&gt;catch&lt;/code&gt; tem que deixar seu programa num estado consistente, não importa o que aconteça no &lt;code&gt;try&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Assim, uma boa prática é começar com uma estrutura &lt;code&gt;try...catch...finally&lt;/code&gt; quando for escrever um código que talvez lance exceções. &lt;strong&gt;Isso ajuda a definir o que o usuário do código deve esperar, independente do que ocorra de errado no código que é executado no &lt;code&gt;try&lt;/code&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Exemplo:

&lt;ul&gt;
&lt;li&gt;Um código que acesse um arquivo e consulte alguns objetos em série:&lt;/li&gt;
&lt;li&gt;Começamos com um teste de unidade que mostra como capturar uma exceção se o arquivo não existir:
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Test(expected = StorageException.class)
public void retrieveSectionShouldThrowOnInvalidFileName() {
    sectionStore.retrieveSection("invalid - file");
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;O teste nos leva a criar esse stub:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public List&amp;lt;RecordedGrip&amp;gt; retrieveSection(String sectionName) {
    // dummy return until we have a real implementation
    return new ArrayList&amp;lt;RecordedGrip&amp;gt;();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Nosso teste falha porque ele não lança uma exceção. Agora, mudamos nossa implementação de modo a tentar acessar um arquivo inválido, lançando uma exceção:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public List&amp;lt;RecordedGrip&amp;gt; retrieveSection(String sectionName) {
    try {
        FileInputStream stream = new FileInputStream(sectionName);
    } catch (Exception e) {
        throw new StorageException("retrieval error", e);
    }
    return new ArrayList&amp;lt;RecordedGrip&amp;gt;();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Agora o teste funciona porque captura a exceção.&lt;/li&gt;
&lt;li&gt;Refatorando para a exceção que realmente é lançada pelo &lt;code&gt;FileInputStream&lt;/code&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public List&amp;lt;RecordedGrip&amp;gt; retrieveSection(String sectionName) {
    try {
        FileInputStream stream = new FileInputStream(sectionName);
        stream.close();
    } catch (FileNotFoundException e) {
        throw new StorageException("retrieval error”, e);
    }
    return new ArrayList&amp;lt;RecordedGrip&amp;gt;();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Use exceções não verificadas
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Exceções verificadas violão o princípio do Aberto-Fechado&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Se lançar uma exceção a ser verificada a partir de um método em seu código e o catch estiver três níveis acima, &lt;strong&gt;será preciso declará-la na assinatura de cada método entre você e o catch&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Isso significa que uma modificação em um nível mais baixo do software pode forçar a alteração de assinaturas em muitos níveis mais altos.&lt;/li&gt;
&lt;li&gt;Os módulos precisaram ser alterados mesmo que nada tenha realmente mudado.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;O propósito de exceções é que elas lhe permitem tratar erros distantes, porém as exceções verificadas quebram o encapsulamento&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Exceções verificadas podem às vezes ser úteis se estiver criando uma biblioteca crítica. Mas no desenvolvimento geral, os custos da dependência superam as vantagens.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Forneça exceções com contexto
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Cada exceção lançada deve fornecer contexto suficiente para determinar a fonte e a localização de um erro.&lt;/li&gt;
&lt;li&gt;No Java temos a &lt;code&gt;stack trace&lt;/code&gt; de qualquer exceção. Porém ela não consegue dizer o motivo da falha da operação.&lt;/li&gt;
&lt;li&gt;Crie mensagens de erro informativas e as passe juntamente com as exceções. &lt;/li&gt;
&lt;li&gt;Mencione a operação que falhou e o tipo de falha.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Defina as classes de exceções segundo as necessidades do chamador
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Exemplo que cobre todas as possíveis exceções:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ACMEPort port = new ACMEPort(12);

try {
    port.open();
} catch (DeviceResponseException e) {
    reportPortError(e);
    logger.log("Device response exception", e);
} catch (ATM1212UnlockedException e) {
    reportPortError(e);
    logger.log("Unlock exception", e);
} catch (GMXError e) {
    reportPortError(e);
    logger.log("Device response exception");
} finally {
    …
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;A estrutura acima possui muita duplicação! E na maioria dos casos de tratamento de exceções, o que fazemos é relativamente padrão, independente da situação no momento.&lt;/li&gt;
&lt;li&gt;Temos que registar um erro e nos certificar que podemos prosseguir.&lt;/li&gt;
&lt;li&gt;Nesse caso podemos simplificar o código pegando um tipo comum de exceção:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LocalPort port = new LocalPort(12);
try {
    port.open();
} catch (PortDeviceFailure e) {
    reportError(e);
    logger.log(e.getMessage(), e);
} finally {
    …
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Assim temos a classe &lt;code&gt;LocalPort&lt;/code&gt; é um simples wrapper (empacotador) que captura e traduz as exceções:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class LocalPort {

    private ACMEPort innerPort;

    public LocalPort(int portNumber) {
        innerPort = new ACMEPort(portNumber);
    }

    public void open() {
        try {
            innerPort.open();
        } catch (DeviceResponseException e) {
            throw new PortDeviceFailure(e);
        } catch (ATM1212UnlockedException e) {
            throw new PortDeviceFailure(e);
        } catch (GMXError e) {
            throw new PortDeviceFailure(e);
        }
    }
    …
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Esses empacotadores podem ser muito úteis.&lt;/li&gt;
&lt;li&gt;Essa abordagem acima é a melhor prática que existe.&lt;/li&gt;
&lt;li&gt;Com isso, minimizamos as dependências nelas.&lt;/li&gt;
&lt;li&gt;Assim é fácil migrar para outra biblioteca no futuro sem grandes problemas.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Defina o fluxo normal
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Um código que soma as despesas em um aplicativo de finanças:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;try {
    MealExpenses expenses = expenseReportDAO.getMeals(employee.getID());
    m_total += expenses.getTotal();
} catch(MealExpensesNotFound e) {
    m_total += getMealPerDiem();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Nesse código, se as refeições (meals) forem um custo, elas se tornam parte do total. Caso contrário, o funcionário recebe uma quantia para ajuda de custos (PerDiem) pela refeição daquele dia. Assim, a &lt;strong&gt;exceção confunde a lógica&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Nesse caso seria melhor não ter que lidar com o caso especial, da seguinte forma:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MealExpenses expenses = expenseReportDAO.getMeals(employee.getID());
m_total += expenses.getTotal();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;E para deixar o código ainda mais simples, alterando o &lt;code&gt;ExpenseReportDAO&lt;/code&gt; para que ele sempre retorne um objeto &lt;code&gt;MealExpenses&lt;/code&gt;. Se não houver gastos com refeições, ele retorna um objeto &lt;code&gt;PerDiemMealExpenses&lt;/code&gt; que retorna a diária como seu total:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class PerDiemMealExpenses implements MealExpenses {
    public int getTotal() {
        // retorna a ajuda de custo padrão
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso se chama padrão Special Case (Padrão de caso especial). Você cria uma classe ou configure um objeto de modo que ele trate de um caso especial para você. Com isso o código do cliente não precisa lidar com um comportamento diferente. Este fica encapsulado num objeto de caso especial.&lt;/p&gt;

&lt;h2&gt;
  
  
  Não retorne null
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public void registerItem(Item item) {
    if (item != null) {
        ItemRegistry registry = peristentStore.getItemRegistry();
        if (registry != null) {
            Item existing = registry.getItem(item.getID());
            if (existing.getBillingPeriod().hasRetailOwner()) {
                existing.register(item);
            }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Quando retornamos &lt;code&gt;null&lt;/code&gt;, estamos criando mais trabalho para nós mesmos e jogando problemas em cima de nossos chamadores. Só basta esquecer uma verificação &lt;code&gt;null&lt;/code&gt; para que o aplicativo fique fora de controle.&lt;/li&gt;
&lt;li&gt;Percebeu que não havia uma verificação de &lt;code&gt;null&lt;/code&gt; na segunda linha do &lt;code&gt;if&lt;/code&gt; aninhado? E se &lt;code&gt;peristentStore&lt;/code&gt; fosse &lt;code&gt;null&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;O problema do código acima é a quantidade de coisas que podem ser &lt;code&gt;null&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Em vez de retornar &lt;code&gt;null&lt;/code&gt; de um método, lance uma exceção&lt;/strong&gt; ou um objeto SPECIAL CASE!&lt;/li&gt;
&lt;li&gt;Se um terceiro método retornar &lt;code&gt;null&lt;/code&gt; use o empacotamento ou o objeto de caso especial.&lt;/li&gt;
&lt;li&gt;Outro exemplo de código que retorna null:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;List&amp;lt;Employee&amp;gt; employees = getEmployees();

if (employees != null) {
    for(Employee e : employees) {
        totalPay += e.getPay();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Agora usando uma lista varia em vez de &lt;code&gt;null&lt;/code&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;List&amp;lt;Employee&amp;gt; employees = getEmployees();
for(Employee e : employees) {
    totalPay += e.getPay();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E no método &lt;code&gt;getEmployees&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public List&amp;lt;Employee&amp;gt; getEmployees() {
    if( .. there are no employees .. )
        return Collections.emptyList();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Com isso minimizamos a chande &lt;code&gt;NullPointerException&lt;/code&gt; e o código será mais limpo.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Não passe null
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Retornar &lt;code&gt;null&lt;/code&gt; dos métodos é ruim, mas passar &lt;code&gt;null&lt;/code&gt; para eles é pior ainda.&lt;/li&gt;
&lt;li&gt;A menos que seja uma API que espere receber &lt;code&gt;null&lt;/code&gt;, devemos evitar passá-lo.&lt;/li&gt;
&lt;li&gt;Exemplo do porquê:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class MetricsCalculator {
    public double xProjection(Point p1, Point p2) {
        return (p2.x – p1.x) * 1.5;
    }
    …
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Se alguém passar &lt;code&gt;null&lt;/code&gt; para o método acima receberemos uma &lt;code&gt;NullPointerException&lt;/code&gt;&lt;/strong&gt;!&lt;/li&gt;
&lt;li&gt;Poderíamos melhor isso lançando uma exceção:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class MetricsCalculator {

    public double xProjection(Point p1, Point p2) {
        if (p1 == null || p2 == null) {
            throw InvalidArgumentException("Invalid argument for MetricsCalculator.xProjection");
        }
        return (p2.x – p1.x) * 1.5;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Melhorou, porém passar &lt;code&gt;null&lt;/code&gt; é sinal de problema e pode gerar mais erros por descuido.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Um código limpo é legível, mas também robusto.&lt;/li&gt;
&lt;li&gt;Podemos fazer esse tipo de código se enxergarmos o tratamento de erro como uma preocupação à parte, algo visível independentemente de nossa lógica principal.&lt;/li&gt;
&lt;li&gt;Com isso damos um grande passo na capacidade de manutenção do código.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>books</category>
      <category>codequality</category>
    </item>
    <item>
      <title>Anotações Capítulo 6: Objects and Data Structures</title>
      <dc:creator>Jonilson Sousa</dc:creator>
      <pubDate>Fri, 11 Jun 2021 17:10:27 +0000</pubDate>
      <link>https://dev.to/jonilsonds9/anotacoes-capitulo-6-objects-and-data-structures-58jg</link>
      <guid>https://dev.to/jonilsonds9/anotacoes-capitulo-6-objects-and-data-structures-58jg</guid>
      <description>&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;“Há um motivo para declararmos nossas variáveis como privadas. Não queremos que ninguém dependa delas”&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;Assim temos a liberdade para alterar o tipo ou a implementação;&lt;/li&gt;
&lt;li&gt;Porque, então, tantos programadores adicionam automaticamente métodos de acesso em seus objetos, como se fossem públicas?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Abstração de dados
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Representação de dados de um ponto no plano cartesiano:&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Caso concreto&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Point {
    public double x;
    public double y;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Caso abstrato&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public interface Point {
    double getX();
    double getY();
    void setCartesian(double x, double y);
    double getR();
    double getTheta();
    void setPolar(double r, double theta);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;“Assim, no &lt;strong&gt;“caso abstrato”&lt;/strong&gt; não há como dizer se a implementação possui coordenadas retangulares ou polares. Pode não ser nenhuma! E ainda assim a interface representa de modo claro uma estrutura de dados.”&lt;/li&gt;
&lt;li&gt;“Os métodos exigem uma regra de acesso. Você pode ler as coordenadas individuais independente, mas deve configurá-las juntas como uma operação atômica”.&lt;/li&gt;
&lt;li&gt;Já no &lt;strong&gt;“caso concreto”&lt;/strong&gt; está implementada em coordenadas retangulares, e nos obriga a manipulá-las independentemente. Isso expõe a implementação. &lt;/li&gt;
&lt;li&gt;A implementação no &lt;strong&gt;“caso concreto”&lt;/strong&gt; seria exposta mesmo se as variáveis fossem privadas e estivéssemos usando métodos únicos de escrita e leitura de variáveis.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;“Ocultar a implementação não é só uma questão de colocar uma camada de funções entre as variáveis. Ocultar a implementação tem a ver com abstrações!”&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;Uma classe não passa suas variáveis simplesmente por meio de métodos getters e setters.&lt;/li&gt;
&lt;li&gt;Em vez disso, ele expõe interfaces abstratas que permitem que seus usuários manipulem a &lt;em&gt;essência&lt;/em&gt; dos dados, sem precisar saber sua implementação.&lt;/li&gt;
&lt;li&gt;Veja as listagens abaixo, a primeira usa termos concretos para comunicar o nível de combustível de um veículo, enquanto a segunda faz isso com a abstração da porcentagem.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public interface Vehicle {
    double getFuelTankCapacityInGallons();
    double getGallonsOfGasoline();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public interface Vehicle {
    double getPercentFuelRemaining();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No primeiro caso, você tem certeza de que são apenas métodos acessores (getter e setter). No segundo, não há como saber o tipo de dados.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Nos casos acima, o segundo é preferível. Não queremos expor os detalhes de nossos dados&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Queremos expressar nossos dados de forma abstrata. Isso não se consegue meramente através de interfaces e/ou getters e setters. É preciso pensar bastante na melhor maneira de representar os dados que um objeto contém.&lt;/li&gt;
&lt;li&gt;A pior opção é adicionar levianamente métodos getter e setter.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Anti-Simetria de Dados/Objeto
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Os objetos usam abstrações para esconder seus dados, e expõem as funções que operam em tais dados&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;As estruturas de dados expõem seus dados e não possuem funções significativas&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Veja a classe de forma procedural:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Square {
    public Point topLeft;
    public double side;
}

public class Rectangle {
    public Point topLeft;
    public double height;
    public double width;
}

public class Circle {
    public Point center;
    public double radius;
}

public class Geometry {
    public final double PI = 3.141592653589793;

    public double area(Object shape) throws NoSuchShapeException {
        if (shape instanceof Square) {
            Square s = (Square)shape;
            return s.side * s.side;
        } else if (shape instanceof Rectangle) {
            Rectangle r = (Rectangle)shape;
            return r.height * r.width;
        } else if (shape instanceof Circle) {
            Circle c = (Circle)shape;
            return PI * c.radius * c.radius;
        }
        throw new NoSuchShapeException();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nesse exemplo a classe &lt;code&gt;Geometry&lt;/code&gt; opera sobre as três outras classes que são simples estruturas de dados sem qualquer atividade. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Esse exemplo anterior é procedural, mas nem sempre. Se adicionássemos uma função &lt;code&gt;perimeter()&lt;/code&gt; à &lt;code&gt;Geometry&lt;/code&gt;, as demais classes não seriam afetadas! Assim como outras que dependesse delas!&lt;/li&gt;
&lt;li&gt;Porém se adicionarmos uma nova classe &lt;code&gt;shape&lt;/code&gt;, teremos que alterar todas as funções em &lt;code&gt;Geometry&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Agora uma solução orientada a objeto:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Square implements Shape {
    private Point topLeft;
    private double side;

    public double area() {
        return side*side;
    }
}

public class Rectangle implements Shape {
    private Point topLeft;
    private double height;
    private double width;

    public double area() {
        return height * width;
    }
}

public class Circle implements Shape {
    private Point center;
    private double radius;
    public final double PI = 3.141592653589793;

    public double area() {
        return PI * radius * radius;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O método &lt;code&gt;area()&lt;/code&gt; é &lt;em&gt;polifórmico&lt;/em&gt;, assim não é necessária a classe &lt;code&gt;Geometry&lt;/code&gt;. Portanto, se adicionarmos uma nova forma, nenhuma das funções existentes serão afetadas, mas se adicionarmos uma nova função, todas as classes &lt;code&gt;shape&lt;/code&gt; deverão ser alteradas.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Duas definições complementares, mas praticamente opostas:
&lt;strong&gt;“O código procedural (usado em estruturas de dados) facilita a adição de novas funções sem precisar alterar as estruturas de dados existentes. O código orientado a objeto (OO), por outro lado, facilita a adição de novas classes sem precisar alterar as funções existentes”&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;O inverso também é verdade:
&lt;strong&gt;“O código procedural dificulta a adição de novas estruturas de dados, pois todas as funções teriam de ser alteradas. O código OO dificulta a adição de novas funções, pois todas as classes teriam de ser alteradas”&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;“O que é difícil para a OO é fácil para o procedural, e o que é difícil para o procedural é fácil para a OO”&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Quando desejarmos adicionar novos tipos de dados em vez de novas funções, os objetos e OO são mais apropriados. &lt;/li&gt;
&lt;li&gt;Por outro lado, se desejarmos adicionar novas funções em vez de tipos de dados, estruturas de dados e código procedural são mais adequados.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Programadores experientes sabem que a ideia de que tudo é um objeto “é um mito”. Às vezes, você realmente “deseja” estruturas de dados simples com procedimentos operando nelas&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A lei de Demeter
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;“Um módulo não deve enxergar o interior dos objetos que ele manipula”&lt;/strong&gt;. &lt;/li&gt;
&lt;li&gt;Objetos escondem seus dados e expõem as operações.&lt;/li&gt;
&lt;li&gt;Um objeto não deve expor sua estrutura interna por meio dos métodos acessores, pois isso seria expor sua estrutura interna.&lt;/li&gt;
&lt;li&gt;A lei fala que um método “f” de uma classe “C” só deve chamar os métodos de: &lt;strong&gt;C&lt;/strong&gt;, &lt;strong&gt;um objeto criado por “f”&lt;/strong&gt;, &lt;strong&gt;um objeto passado como parâmetro para “f”&lt;/strong&gt;, &lt;strong&gt;um objeto dentro de uma instância da variável “C”&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;O método &lt;strong&gt;não&lt;/strong&gt; deve chamar os métodos em objetos retornados por qualquer outra das funções permitidas.&lt;/li&gt;
&lt;li&gt;“Fale apenas com conhecidos, não com estranhos”.&lt;/li&gt;
&lt;li&gt;Um exemplo que viola essa lei:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;final String outputDir = ctxt.getOptions().getScratchDir().getAbsolutePath();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Trem descarrilhado
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Esse código acima costuma ser chamado de acidente de trem, pois parece com um monte de carrinhos de trem acoplados.&lt;/li&gt;
&lt;li&gt;Cadeias de chamadas como essa geralmente são consideradas descuidadas e devem ser evitadas. É melhor dividi-las assim:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Options opts = ctxt.getOptions();
File scratchDir = opts.getScratchDir();
final String outputDir = scratchDir.getAbsolutePath();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Essa função acima tem muito conhecimento&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Se &lt;code&gt;ctxt&lt;/code&gt;, &lt;code&gt;options&lt;/code&gt; e &lt;code&gt;scracthDir&lt;/code&gt; forem objetos, então este código viola a lei, já que sua estrutura interna está exposta. Porém, se forem apenas estruturas de dados sem atividades, então elas naturalmente expõem suas estruturas internas, e não se aplica a lei.&lt;/li&gt;
&lt;li&gt;O uso de assessores (getters) confunde as questões. Se o código tiver escrito como abaixo, não teríamos dúvidas:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;final String outputDir = ctxt.options.scratchDir.absolutePath;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Seria menos confuso se as estruturas de dados tivessem apenas variáveis públicas e nenhuma função, e os objetos apenas variáveis privadas e funções públicas&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Híbridos
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Essa confusão leva a estruturas híbridas ruins, que são metade objeto e metade estrutura de dados.&lt;/li&gt;
&lt;li&gt;Funções que fazem algo significativo, e variáveis ou métodos de acesso e de alteração públicos, que para todos os efeitos, tornam públicas as variáveis privadas, deixando com que funções externas usem tais variáveis de forma como um programa procedural usaria.&lt;/li&gt;
&lt;li&gt;Esses híbridos dificultam tanto a adição de novas funções como de novas estruturas de dados.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;São a pior coisa em ambas as condições. Evite criá-los&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Estruturas ocultas
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Se &lt;code&gt;ctxt&lt;/code&gt; for um objeto, devemos dizê-lo para fazer algo, não devemos perguntá-lo sobre sua estrutura interna.&lt;/li&gt;
&lt;li&gt;Devemos sempre pedir para que o próprio objeto faça a ação:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BufferedOutputStream bos = ctxt.createScratchFileStream(classFileName);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Esse código acima é algo razoável para um objeto fazer.&lt;/li&gt;
&lt;li&gt;Dessa forma o &lt;code&gt;ctxt&lt;/code&gt; esconde sua estrutura interna e evita que a função atual viole a Lei de Demeter ao navegar por objetos os quais ela não deveria enxergar.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Objetos de transferência de dados
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A forma perfeita de uma estrutura de dados é uma classe com variáveis públicas e nenhuma função&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Geralmente chama-se isso de objeto de transferência de dados, ou DTO.&lt;/li&gt;
&lt;li&gt;Os DTOs, são estruturas muito úteis, para se comunicar com banco de dados ou mensagens e assim por diante.&lt;/li&gt;
&lt;li&gt;O formulário “bean” abaixo, têm variáveis privadas manipuladas por métodos de escrita e leitura, e o aparente encapsulamento dos beans parece fazer alguns puristas da OO se sentirem melhores:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Address {
    private String street;
    private String streetExtra;
    private String city;
    private String state;
    private String zip;

    public Address(String street, String streetExtra, String city, String state, String zip) {
        this.street = street;
        this.streetExtra = streetExtra;
        this.city = city;
        this.state = state;
        this.zip = zip;
    }

    public String getStreet() {
        return street;
    }

    public String getStreetExtra() {
        return streetExtra;
    }

    public String getCity() {
        return city;
    }

    public String getState() {
        return state;
    }

    public String getZip() {
        return zip;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  O Active Record
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;São formas especiais de DTOs;&lt;/li&gt;
&lt;li&gt;São estruturas de dados com variáveis públicas;&lt;/li&gt;
&lt;li&gt;Mas eles tipicamente possuem métodos de navegação, como save e find.&lt;/li&gt;
&lt;li&gt;São traduções diretas das tabelas de bancos de dados ou de outras fontes de dados.&lt;/li&gt;
&lt;li&gt;Costumamos ver desenvolvedores tratando essas estruturas de dados como se fossem objetos, colocando regras de negócios. Isso é complicado, pois cria um híbrido.&lt;/li&gt;
&lt;li&gt;A solução para o ponto anterior é tratar o Active Record como uma estrutura de dados e criar objetos separados que contenham as regras de negócio e que ocultem seus dados internos.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Objetos expõem as ações e ocultam os dados. Assim, facilita a adição de novos tipos de objetos sem precisar modificar as ações existentes e dificulta a inclusão de novas atividades em objetos existentes.&lt;/li&gt;
&lt;li&gt;As estruturas de dados expõem os dados e não possuem ações significativas. Assim, facilita a adição de novas ações às estruturas de dados existentes e dificulta a inclusão de novas estruturas de dados em funções existentes.&lt;/li&gt;
&lt;li&gt;Às vezes buscamos flexibilidade para adicionar novos tipos de dados, e optamos por objetos.&lt;/li&gt;
&lt;li&gt;Às vezes buscamos flexibilidade para adicionar novas ações, e optamos por estrutura de dados e procedimentos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;“Bons desenvolvedores de software entendem essas questões sem preconceito e selecionam a abordagem que melhor se aplica no momento”&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>books</category>
      <category>codequality</category>
    </item>
    <item>
      <title>Anotações Capítulo 5: Formatting</title>
      <dc:creator>Jonilson Sousa</dc:creator>
      <pubDate>Wed, 09 Jun 2021 14:09:46 +0000</pubDate>
      <link>https://dev.to/jonilsonds9/anotacoes-capitulo-5-formatting-218</link>
      <guid>https://dev.to/jonilsonds9/anotacoes-capitulo-5-formatting-218</guid>
      <description>&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;“Você deve tomar conta para que seu código fique bem formatado”&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;Escolha regras simples e aplique de forma consistente.&lt;/li&gt;
&lt;li&gt;Em equipe, todos devem concordar com uma única série de regras de formatação.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Objetivo da formatação
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A formatação de código é importante.&lt;/li&gt;
&lt;li&gt;Serve como comunicação.&lt;/li&gt;
&lt;li&gt;Legibilidade do código terá um grande efeito em todas as mudanças futuras.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Formatação vertical
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Há uma grande diversidade de tamanhos e diferenças de estilo.&lt;/li&gt;
&lt;li&gt;As linhas verticais mostram os comprimentos mínimo e máximo.&lt;/li&gt;
&lt;li&gt;Arquivos pequenos costumam ser mais fáceis de se entender do que os grandes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A metáfora do jornal
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;“No topo você espera ver uma manchete que lhe diz do que se trata a história e lhe permite decidir se deseja ou não ler”.&lt;/li&gt;
&lt;li&gt;Primeiro parágrafo é a sinopse da história.&lt;/li&gt;
&lt;li&gt;O demais detalhes vem no decorrer da leitura.&lt;/li&gt;
&lt;li&gt;Queremos que o código fonte seja como artigo de jornal.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Espaçamento vertical entre conceitos
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Há linhas em branco que separam a declaração e a importação do pacote e cada uma das funções.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;“Cada linha em branco indica visualmente a separação entre conceitos”&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Retirar as linhas em branco, gera um efeito muito ruim na legibilidade do código.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Continuidade vertical
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A continuidade vertical indica uma associação íntima.&lt;/li&gt;
&lt;li&gt;Linhas de código que estão intimamente relacionadas devem aparecer verticalmente unidas.&lt;/li&gt;
&lt;li&gt;Comentários inúteis quebram essa intimidade de duas variáveis:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class ReporterConfig {

    /**
    * The class name of the reporter listener
    */
    private String m_className;

    /**
    * The properties of the reporter listener
    */
    private List&amp;lt;Property&amp;gt; m_properties = new         ArrayList&amp;lt;Property&amp;gt;();

    public void addProperty(Property property) {
        m_properties.add(property);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Removendo os comentários fica mais fácil de ler:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class ReporterConfig {

    private String m_className;
    private List&amp;lt;Property&amp;gt; m_properties = new ArrayList&amp;lt;Property&amp;gt;();

    public void addProperty(Property property) {
        m_properties.add(property);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esse último exemplo, o código cabe numa única visão, podemos compreender todo o método sem ter que mover a cabeça ou os olhos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Distância vertical
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Os conceitos intimamente relacionados para conceitos em arquivos separados.&lt;/li&gt;
&lt;li&gt;Não devemos separar em arquivos distintos conceitos intimamente relacionados, a menos que tenha uma razão muito boa.&lt;/li&gt;
&lt;li&gt;A separação vertical deles deve ser uma medida do quão importante eles são para a inteligibilidade um do outro.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Devemos declarar variáveis o mais próximo possível de onde serão usadas”&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Exemplo: Devemos declarar variáveis de controle para loops dentro da estrutura de iteração:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public int countTestCases() {
    int count= 0;
    for (Test each : tests)
        count += each.countTestCases();
    return count;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Em alguns casos pode-se declarar uma variável no início de um bloco ou logo depois de um loop em uma função longa:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for (XmlTest test : m_suite.getTests()) {
    TestRunner tr = m_runnerFactory.newTestRunner(this, test);
    tr.addListener(m_textReporter);
    m_testRunners.add(tr);

    invoker = tr.getInvoker();

    for (ITestNGMethod m : tr.getBeforeSuiteMethods()) {
        beforeSuiteMethods.put(m.getMethod(), m);
    }

    for (ITestNGMethod m : tr.getAfterSuiteMethods()) {
        afterSuiteMethods.put(m.getMethod(), m);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Variáveis de Instância&lt;/strong&gt;: Devemos declarar as variáveis de instância no início da classe. Isso não deve aumentar a distância vertical entre tais variáveis, elas serão usadas por muitos, senão todos, os métodos da classe.&lt;/li&gt;
&lt;li&gt;O importante é que as variáveis de instância sejam declaradas em um local bem conhecido. 
Todos devem saber onde buscar as declarações.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Funções dependentes&lt;/strong&gt;: Se uma função chama outra, elas devem ficar verticalmente próximas. Assim, a que chama deve ficar acima da que for chamada. Isso dá um fluxo natural ao programa.&lt;/li&gt;
&lt;li&gt;Assim, os leitores poderão confiar que as declarações daquelas funções virão logo em seguida.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Afinidade conceitual&lt;/strong&gt;: Quanto maior a afinidade, menor deve ser a distância entre eles. &lt;/li&gt;
&lt;li&gt;A afinidade se baseia numa dependência direta. Uma função chamando outra. Uma função usando uma variável.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Um grupo de funções que efetuam uma operação parecida cria uma afinidade&lt;/strong&gt;. Exemplo:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Assert {
    static public void assertTrue(String message, boolean condition) {
        if (!condition)
            fail(message);
    }

    static public void assertTrue(boolean condition) {
        assertTrue(null, condition);
    }

    static public void assertFalse(String message, boolean condition) {
        assertTrue(message, !condition);
    }

    static public void assertFalse(boolean condition) {
        assertFalse(null, condition);
    }
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Essas funções possuem uma afinidade conceitual forte, pois compartilham de uma mesma convenção de nomes e efetuam variações de uma mesma tarefa. Bem como o fato de uma chamar a outra.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ordenação vertical
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Desejamos que as chamadas das dependências da função apontem para baixo;&lt;/li&gt;
&lt;li&gt;No caso, “a função chamada deve ficar embaixo da que a chama”;&lt;/li&gt;
&lt;li&gt;Cria um fluxo natural para baixo no módulo do código-fonte, de um nível maior para um menor.&lt;/li&gt;
&lt;li&gt;Assim os detalhes de baixo nível venham por último.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Formatação horizontal
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;“Devemos nos esforçar para manter nossas linhas curtas”&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;O antigo limite de 80 de Hollerith é arbitrário;&lt;/li&gt;
&lt;li&gt;Com 100 linhas ou 120 ainda é aceitável, porém ultrapassar 120 caracteres é uma falta de cuidado;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Espaçamento e continuidade horizontal
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Operadores de atribuição &lt;strong&gt;entre&lt;/strong&gt; espaços em branco:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int lineSize = line.length();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Essas instruções tem dois lados distintos, o lado esquerdo e o lado direito. Assim, os espaços tornam essa separação óbvia.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Porém &lt;strong&gt;não&lt;/strong&gt; coloque espaços entre os nomes das funções e os parênteses de abertura. Isso porque a função e seus parâmetros estão intimamente relacionados;&lt;/li&gt;
&lt;li&gt;Bem como separar os parâmetros entre parênteses na chamada da função realçar a vírgula e mostram que estão separados;&lt;/li&gt;
&lt;li&gt;Espaço em branco entre operadores é para destacar a prioridade dos mesmo;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Alinhamento horizontal
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Esse tipo de alinhamento não é prático;&lt;/li&gt;
&lt;li&gt;Parece enfatizar as coisas erradas e afasta o propósito real;&lt;/li&gt;
&lt;li&gt;As ferramentas de reformatação automática geralmente eliminam esse tipo de alinhamento;&lt;/li&gt;
&lt;li&gt;É melhor não usar esse tipo de alinhamento;&lt;/li&gt;
&lt;li&gt;Se tiver listas longas que precisam ser alinhadas, “o problema está no tamanho das listas”e não na falta de alinhamento;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Indentação
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Um código-fonte é mais como uma hierarquia do que algo esquematizado;&lt;/li&gt;
&lt;li&gt;Informações pertinentes ao arquivo, classes individuais dentro do arquivo, aos métodos das classes, aos blocos dentro dos métodos.&lt;/li&gt;
&lt;li&gt;Cada nível dessa hierarquia é um escopo.&lt;/li&gt;
&lt;li&gt;E para tornar visível essa hierarquia indentamos o código.&lt;/li&gt;
&lt;li&gt;Os programadores dependem bastante dessa indentação.&lt;/li&gt;
&lt;li&gt;Elas alinham visualmente na esquerda as linhas para ver em qual escopo eles estão.&lt;/li&gt;
&lt;li&gt;Assim a navegação e a compreensão do código para o programador é facilitada, ele sempre vai procurar a declaração variáveis mais a esquerda, etc.&lt;/li&gt;
&lt;li&gt;A mesma versão de um código sem indentação é quase incompreensível.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ignorando a indentação&lt;/strong&gt;: Podemos querer não fazer a indentação mas no fim voltamos e fazemos, é uma necessidade.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Escopos minúsculos
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Estruturas while ou for minúsculas, é complicado para uma boa indentação.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Regra de equipes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Todo programador tem suas regras de formatação prediletas;&lt;/li&gt;
&lt;li&gt;Mais em uma equipe, as regras são dela;&lt;/li&gt;
&lt;li&gt;A equipe deve escolher um único estilo de formatação e todos devem usá-lo;&lt;/li&gt;
&lt;li&gt;Assim o código tem estilo consistente;&lt;/li&gt;
&lt;li&gt;O leitor precisa poder confiar que as formatações que ele vir em uma arquivo-fonte terão o mesmo significado nos outros.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Regras de formatação do Uncle Bob
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Considere este um exemplo de como o código torna o melhor documento padrão de codificação:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class CodeAnalyzer implements JavaFileAnalysis {
    private int lineCount;
    private int maxLineWidth;
    private int widestLineNumber;
    private LineWidthHistogram lineWidthHistogram;
    private int totalChars;

    public CodeAnalyzer() {
        lineWidthHistogram = new LineWidthHistogram();
    }

    public static List&amp;lt;File&amp;gt; findJavaFiles(File parentDirectory) {
        List&amp;lt;File&amp;gt; files = new ArrayList&amp;lt;File&amp;gt;();
        findJavaFiles(parentDirectory, files);
        return files;
    }

    private static void findJavaFiles(File parentDirectory, List&amp;lt;File&amp;gt; files) {
        for (File file : parentDirectory.listFiles()) {
            if (file.getName().endsWith(".java"))
                files.add(file);
            else if (file.isDirectory())
                findJavaFiles(file, files);
        }
    }

    public void analyzeFile(File javaFile) throws Exception {
        BufferedReader br = new BufferedReader(new FileReader(javaFile));
        String line;
        while ((line = br.readLine()) != null)
            measureLine(line);
    }

    private void measureLine(String line) {
        lineCount++;
        int lineSize = line.length();
        totalChars += lineSize;
            lineWidthHistogram.addLine(lineSize, lineCount);
        recordWidestLine(lineSize);
    }

    private void recordWidestLine(int lineSize) {
        if (lineSize &amp;gt; maxLineWidth) {
            maxLineWidth = lineSize;
            widestLineNumber = lineCount;
        }
    }

    public int getLineCount() {
        return lineCount;
    }

    public int getMaxLineWidth() {
        return maxLineWidth;
    }

    public int getWidestLineNumber() {
        return widestLineNumber;
    }

&amp;lt;restante do código&amp;gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>books</category>
      <category>codequality</category>
    </item>
    <item>
      <title>Anotações Capítulo 4: Comments</title>
      <dc:creator>Jonilson Sousa</dc:creator>
      <pubDate>Tue, 18 May 2021 20:36:31 +0000</pubDate>
      <link>https://dev.to/jonilsonds9/anotacoes-capitulo-4-comments-51lc</link>
      <guid>https://dev.to/jonilsonds9/anotacoes-capitulo-4-comments-51lc</guid>
      <description>&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;“Não insira comentários num código ruim, reescreva-o”&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nada pode ser tão útil quanto um comentário bem colocado. Nada consegue amontoar um módulo mais do que comentários dogmáticos e supérfluos. Nada pode ser tão prejudicial quanto um velho comentário mal feito que dissemina mentiras e informações incorretas.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Comentários são, no máximo, um mal necessário.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;“O uso adequado de comentários é para compensar nosso fracasso em nos expressar no código”.&lt;br&gt;
Quando precisar “criar um comentário, pense bem e veja se não há como se expressar através do código em si”.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Comentários geralmente são mentirosos, principalmente aqueles antigos, isso porque os programadores não conseguem manter eles atualizados&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Códigos mudam e evoluem, e nem sempre os comentários os acompanham. E geralmente ficam longe do código o qual descrevem.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Comentários imprecisos são muito piores do que nenhum. Eles enganam e iludem.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;“Só se pode encontrar a verdade em um lugar: no código”&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Comentários Compensam um Código Ruim
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Uma das motivações mais comuns para criar comentários é um código ruim.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Quando estamos cientes da bagunça, pensamos que é melhor inserir um comentário. &lt;strong&gt;Não! É melhor limpá-lo&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ao invés de criar comentários para explicar a bagunça, você deve limpar a zona.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Explique-se no código
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Há vezes em que não é possível se expressar direito no código;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mais em vez de termos:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Check to see if the employee is eligible for full benefits
if ((employee.flags &amp;amp; HOURLY_FLAG) &amp;amp;&amp;amp; (employee.age &amp;gt; 65))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Seria melhor criar uma função cujo o nome diga a mesma coisa que você deseja colocar no comentário:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (employee.isEligibleForFullBenefits())
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Comentários Bons
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Certos comentários são necessários ou benéficos.&lt;/li&gt;
&lt;li&gt;Tenha em mente, que o único comentário bom é aquele em que você encontrou uma forma para não escrevê-lo.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Comentários Legais
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Às vezes somos forçados a escrever comentários;&lt;/li&gt;
&lt;li&gt;Frases sobre direitos autorais e autoria são necessárias e lógicas para se colocar no início de um arquivo fonte.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Comentários Informativos
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Às vezes é prático fornecer informações básicas em um comentário. Por exemplo:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Returns an instance of the Responder being tested.
protected abstract Responder responderInstance();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;É um comentário útil, mas sempre que possível é melhor usar o nome da função para transmitir a informação.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Outro exemplo:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// format matched kk:mm:ss EEE, MMM dd, yyyy
Pattern timeMatcher = Pattern.compile("\\d*:\\d*:\\d* \\w*, \\w* \\d*, \\d*");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esse comentário nos permite saber que a expressão regular deve combinar com uma hora e data formatadas com a função &lt;code&gt;SimpleDateFormat.format&lt;/code&gt; usando a string específica com o formato.&lt;/p&gt;

&lt;h3&gt;
  
  
  Explicação da intenção
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Às vezes, um comentário vai além de ser apenas informações úteis sobre a implementação e fornece a intenção por trás de uma decisão.&lt;/li&gt;
&lt;li&gt;Exemplo:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public void testConcurrentAddWidgets() throws Exception {
    WidgetBuilder widgetBuilder = new WidgetBuilder(new Class[ {BoldWidget.class});
    String text = "'''bold text'''";
    ParentWidget parent = new BoldWidget(new MockWidgetRoot(), "'''bold text'''");
    AtomicBoolean failFlag = new AtomicBoolean();
    failFlag.set(false);

    // Essa é a nossa melhor tentativa para conseguir uma condição de corrida.
    // Para isso criamos um grande número de threads.
    for (int i = 0; i &amp;lt; 25000; i++) {
        WidgetBuilderThread widgetBuilderThread = new  WidgetBuilderThread(widgetBuilder, text, parent, failFlag);
        Thread thread = new Thread(widgetBuilderThread);
        thread.start();
    }
    assertEquals(false, failFlag.get());
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Esclarecimento
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Às vezes é bom traduzir o significado de alguns parâmetros ou valores obscuros para algo inteligível. Exemplo:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public void testCompareTo() throws Exception {
    WikiPagePath a = PathParser.parse("PageA");
    WikiPagePath ab = PathParser.parse("PageA.PageB");
    WikiPagePath b = PathParser.parse("PageB");
    WikiPagePath aa = PathParser.parse("PageA.PageA");
    WikiPagePath bb = PathParser.parse("PageB.PageB");
    WikiPagePath ba = PathParser.parse("PageB.PageA");

    assertTrue(a.compareTo(a) == 0); // a == a
    assertTrue(a.compareTo(b) != 0); // a != b
    assertTrue(ab.compareTo(ab) == 0); // ab == ab
    assertTrue(a.compareTo(b) == -1); // a &amp;lt; b
    assertTrue(aa.compareTo(ab) == -1); // aa &amp;lt; ab
    assertTrue(ba.compareTo(bb) == -1); // ba &amp;lt; bb
    assertTrue(b.compareTo(a) == 1); //  b &amp;gt; a
    assertTrue(ab.compareTo(aa) == 1); // ab &amp;gt; aa
    assertTrue(bb.compareTo(ba) == 1); // bb &amp;gt; ba
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Há um risco de um comentário esclarecedor possa estar incorreto. &lt;/p&gt;

&lt;h3&gt;
  
  
  Alerta Sobre Consequências
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Às vezes é útil alertar sobre certas consequências. Por exemplo:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// **Não execute a menos que você tenha tempo disponível.**
public void _testWithReallyBigFile() {
    writeLinesToFile(10000000);

    response.setBody(testFile);
    response.readyToSend(this);
    String responseString = output.toString();
    assertSubString("Content-Length: 1000000000", responseString);
    assertTrue(bytesSent &amp;gt; 1000000000);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O comentário acima explica por que um caso de teste em particular está desabilitado.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Porém atualmente desabilitamos o teste deste caso através do atributo &lt;code&gt;@Ignore&lt;/code&gt; com uma string explanatória adequada: &lt;code&gt;@Ignore(“Leva muito tempo para executar”)&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Outro exemplo:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public static SimpleDateFormat makeStandardHttpDateFormat() {
    //SimpleDateFormat não é uma thread segura,
    //é preciso criar cada instância independentemente.
    SimpleDateFormat df = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z");
    df.setTimeZone(TimeZone.getTimeZone("GMT"));
    return df;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Comentário TODO
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Às vezes é cabível deixar notas “To Do” (“Fazer”) em comentários no formato &lt;code&gt;//TODO&lt;/code&gt;. Exemplo:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// TODO-MdM essas não são necessárias
// Esperamos que isso não esteja mais aqui quando verificarmos o modelo
protected VersionInfo makeVersion() throws Exception {
    return null;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;TODOs&lt;/code&gt; são tarefas que os programadores acham que devem ser efetuadas, mas, por alguma razão, não podem no momento. Pode ser um lembrete para excluir uma instrução desnecessária ou um apelo para que alguém olhe o problema.&lt;/li&gt;
&lt;li&gt;Seja qual for o &lt;code&gt;TODO&lt;/code&gt;, ele não justifica deixar um código ruim no sistema.&lt;/li&gt;
&lt;li&gt;Procure-os regularmente e elimine os que puder.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Destaque
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Pode-se usar um comentário para destacar a importância de algo que talvez pareça irrelevante:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;String listItemContent = match.group(3).trim();
// a função trim é muito importante. Ela remove os espaços
// iniciais que poderiam fazer com o item fosse
// reconhecido como outra lista
new ListItemWidget(this, listItemContent, this.level + 1);
return buildList(text.substring(match.end()));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Javadocs em APIs Públicas
&lt;/h3&gt;

&lt;p&gt;Não há nada de tão prático e satisfatório como uma API pública descrita. Como os javadocs, seria difícil escrever programas Java sem eles. &lt;br&gt;
Mas esses comentários também podem ser enganadores e desonestos como qualquer outro tipo de comentário.&lt;/p&gt;
&lt;h2&gt;
  
  
  Comentários Ruins
&lt;/h2&gt;

&lt;p&gt;A maioria dos comentários cai nesta categoria. Geralmente eles são suportes ou desculpas para um código de baixa qualidade.&lt;/p&gt;
&lt;h3&gt;
  
  
  Murmúrio
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Usar um comentário só porque você sente que deve ou porque o processo o requer é besteira. Se for criar um comentário, crie um bom comentário.&lt;/li&gt;
&lt;li&gt;Exemplo:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public void loadProperties() {
    try {
        String propertiesPath = propertiesLocation + "/" + PROPERTIES_FILE;
        FileInputStream propertiesStream = new FileInputStream(propertiesPath);
        loadedProperties.load(propertiesStream);
    }
    catch(IOException e) {
        // Nenhum arquivo de propriedades significa que todos os padrões estão carregados.
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Não conseguimos entender o que o autor quis dizer. Podemos entender que se cairmos no &lt;code&gt;catch&lt;/code&gt;, todos os padrões estão carregados. Mas quem carrega os padrões? Como foi esse processo? Será que o autor adicionou apenas para não deixar o bloco &lt;code&gt;catch&lt;/code&gt; vazio? Ou ele estava dizendo para ele mesmo para voltar depois e escrever o código que carregaria os padrões?&lt;br&gt;
A alternativa para entender o código seria ver outras partes do sistema para entender. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Assim, qualquer comentário que lhe obrigue a analisar outro módulo em busca de significado não vale os bits que consome&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Comentários Redundantes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Um comentário redundante provavelmente podemos  levar mais tempo para lê-lo do que o código em si. Exemplo:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Método utilitário que retorna quando this.closed é verdadeiro. 
// Lança uma exceção se o tempo limite for atingido.
public synchronized void waitForClose(final long timeoutMillis) throws Exception {
    if(!closed) {
        wait(timeoutMillis);
        if(!closed) 
            throw new Exception("MockResponseSender could not be closed");
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Esse comentário não tem propósito, certamente não é mais informativo do que o código. Não segue nenhum dos tópicos abordados anteriormente.&lt;/p&gt;
&lt;h3&gt;
  
  
  Comentários Enganadores
&lt;/h3&gt;

&lt;p&gt;No exemplo anterior, o comentário indica que o método retornava quando &lt;code&gt;this.closed&lt;/code&gt; &lt;strong&gt;virava&lt;/strong&gt; &lt;code&gt;true&lt;/code&gt;, mas só se o &lt;code&gt;this.closed&lt;/code&gt; &lt;strong&gt;já fosse&lt;/strong&gt; &lt;code&gt;true&lt;/code&gt;, caso contrário, ele esperava por um tempo limite e então lançava uma exceção, caso o &lt;code&gt;this.closed&lt;/code&gt; &lt;strong&gt;não fosse&lt;/strong&gt; &lt;code&gt;true&lt;/code&gt;.&lt;br&gt;
Além de redundante, o comentário ainda estava incorreto com o que realmente acontecia no método.&lt;/p&gt;
&lt;h3&gt;
  
  
  Comentários Imperativos
&lt;/h3&gt;

&lt;p&gt;É tolice ter uma regra dizendo que toda função deva ter um Javadoc, ou toda variável um comentário. Só serão prejudiciais ao código, gerando mentiras e desorganização. Exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
*
* @param title The title of the CD
* @param author The author of the CD
* @param tracks The number of tracks on the CD
* @param durationInMinutes The duration of the CD in minutes
*/
public void addCD(String title, String author, int tracks, int durationInMinutes) {
    CD cd = new CD();
    cd.title = title;
    cd.author = author;
    cd.tracks = tracks;
    cd.duration = duration;
    cdList.add(cd);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Comentários Longos
&lt;/h3&gt;

&lt;p&gt;Às vezes, as pessoas, toda vez que editam um código, adicionam um comentário, e após várias alterações, a quantidade de comentários acumulada parece mais uma redação ou um diário.&lt;/p&gt;

&lt;p&gt;Antes era necessário esses comentários, porém hoje com os sistemas de controle de código se encarregam dessa função.&lt;/p&gt;

&lt;h3&gt;
  
  
  Comentários Ruidosos
&lt;/h3&gt;

&lt;p&gt;Às vezes você vê comentários que nada são além de “chiados”. Eles dizem o óbvio e não fornecem novas informações.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
* Default constructor.
*/
protected AnnualDateRule() {
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/** The day of the month. */
private int dayOfMonth;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;São totalmente irrelevantes que ignoramos. No final eles passam a “mentir” &lt;br&gt;
conforme o código muda.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“Troque a tentação para criar ruídos pela determinação para limpar seu código”.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Ruídos assustadores
&lt;/h3&gt;

&lt;p&gt;Os javadocs também podem ser vistos como ruídos. Qual o objetivo dos Javadocs de uma biblioteca de código livre bem conhecida?&lt;/p&gt;

&lt;p&gt;Geralmente, podem conter erros de cópia já que os programadores não prestam atenção na hora de escrevê-los.&lt;/p&gt;
&lt;h3&gt;
  
  
  Evite o comentário se é possível usar uma função ou uma variável
&lt;/h3&gt;

&lt;p&gt;Veja o código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// o módulo da lista global &amp;lt;mod&amp;gt; depende do
// subsistema do qual fazemos parte?
if (smodule.getDependSubsystems().contains(subSysMod.getSubSy tem()))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Poderíamos evitar o comentário da seguinte forma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ArrayList moduleDependees = smodule.getDependSubsystems();
String ourSubSystem = subSysMod.getSubSystem();
if (moduleDependees.contains(ourSubSystem))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nesse caso o autor pode ter escrito o comentário primeiro e depois o código, o correto seria ele refatorar o código e deixamos como nossa segunda forma.&lt;/p&gt;

&lt;h3&gt;
  
  
  Marcadores de Posição
&lt;/h3&gt;

&lt;p&gt;Algumas vezes os programadores gostam de marcar uma posição determinada no arquivo fonte. Exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Actions //////////////////////////////////
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Só use indicadores quando gerarem benefícios significativos. Se usar excessivamente, eles se tornarão ruídos e serão ignorados.&lt;/p&gt;

&lt;h3&gt;
  
  
  Comentários ao lado de chaves de fechamento
&lt;/h3&gt;

&lt;p&gt;Às vezes, os programadores colocam comentários ao lado de chaves de fechamento. Embora isso possa fazer sentido em funções longas com estruturas muito aninhadas. Nesse caso é melhor reduzir as funções. Exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class wc {
    public static void main(String[] args) {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        String line;
        int lineCount = 0;
        int charCount = 0;
        int wordCount = 0;
        try {
            &amp;lt;códigos aqui&amp;gt;
        } // try
        catch (IOException e) {
            System.err.println("Error:" + e.getMessage());
        } //catch
    } //main
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Créditos e autoria
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/* Adicionado por Rick */
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Os sistemas de controle de versão já fazem essa função, portanto não há necessidade de poluir o código com esses tipos de comentários.&lt;/p&gt;

&lt;h3&gt;
  
  
  Explicação do código em comentários
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Poucas práticas são tão condenáveis quanto explicar o código nos comentários.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Não faça isso!&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Podem fazer com que outros tenham medo de excluir os comentários por pensarem que são importantes.&lt;/li&gt;
&lt;li&gt;É uma grande sujeira!&lt;/li&gt;
&lt;li&gt;Não precisamos deixar código comentado para lembrar deles, exclua o código e os sistemas de controle de versão se lembraram desse código excluído e nunca o perderemos.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Comentários HTML
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;“Códigos HTML em comentários de código fonte são uma aberração”.&lt;/li&gt;
&lt;li&gt;Eles dificultam a leitura dos comentários que seriam fáceis de ler.&lt;/li&gt;
&lt;li&gt;Se precisar extrair comentários para uma página HTML a ferramenta que está utilizando deve ser responsável por isso e não o programador.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Informações não locais
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Se precisar escrever um comentário, então coloque o mesmo perto do código que ele descreve.&lt;/li&gt;
&lt;li&gt;Não forneça informações gerais do sistema no contexto de um comentário local.&lt;/li&gt;
&lt;li&gt;No exemplo abaixo o comentário fala sobre porta, que nem é usada no método e também não há garantia dele ser atualizado quando o código for alterado:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
* Port on which fitnesse would run. Defaults to &amp;lt;b&amp;gt;8082&amp;lt;/b&amp;gt;.
*
* @param fitnessePort
*/
public void setFitnessePort(int fitnessePort) {
    this.fitnessePort = fitnessePort;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Informações excessivas
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;“Não adicione discussões históricas interessantes ou descrições irrelevantes de detalhes em seus comentários”;&lt;/li&gt;
&lt;li&gt;Não precisamos dessas informações contidas no comentário.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conexões nada óbvias
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;“A conexão entre um comentário e o código que ele descreve deve ser óbvia”;&lt;/li&gt;
&lt;li&gt;Um comentário deve estar conectado com o código, assim o leitor pode ler ambos e entender o que foi falado.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;É péssimo quando um comentário também precisa ser explicado!&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cabeçalhos de funções
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;“Funções curtas não requerem muita explicação”&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;Um nome bem selecionado para uma função pequena e que faz apenas uma coisa costuma ser melhor do que um comentário no cabeçalho.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Javadocs em códigos não públicos
&lt;/h3&gt;

&lt;p&gt;Javadocs para um código não voltado para distribuição ao público são uma maldição. Só gera entulho e distração no código.&lt;/p&gt;

</description>
      <category>books</category>
      <category>codequality</category>
    </item>
    <item>
      <title>Anotações Capítulo 3: Functions</title>
      <dc:creator>Jonilson Sousa</dc:creator>
      <pubDate>Fri, 14 May 2021 18:09:17 +0000</pubDate>
      <link>https://dev.to/jonilsonds9/anotacoes-capitulo-3-functions-12gm</link>
      <guid>https://dev.to/jonilsonds9/anotacoes-capitulo-3-functions-12gm</guid>
      <description>&lt;ul&gt;
&lt;li&gt;&lt;p&gt;As funções permaneceram durante a evolução da programação;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;O que torna uma função fácil de ler e entender?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Pequenas!
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;“A primeira regra para funções é que elas devem ser pequenas. A segunda é que precisam ser mais espertas do que isso”.&lt;/li&gt;
&lt;li&gt;Funções devem ter no máximo 20 linhas;&lt;/li&gt;
&lt;li&gt;Kent Beck escreveu um programa (Java/Swing) que ele chamava de “Sparkle” e cada função desse programa tinha duas, ou três, ou quatro linhas e essa deve ser o tamanho das nossas funções.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Blocos e Indentação
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Os blocos dentro de &lt;code&gt;if, else, while&lt;/code&gt; e outros devem ter apenas uma linha. Possivelmente uma chamada de função.&lt;/li&gt;
&lt;li&gt;O nível de indentação de uma função deve ser de, no máximo, um ou dois níveis.&lt;/li&gt;
&lt;li&gt;Facilita a leitura de compreensão das funções.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Faça uma Coisa
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;“AS FUNÇÕES DEVEM FAZER UMA COISA. DEVEM FAZÊ-LA BEM. DEVEM FAZER APENAS ELA”&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Uma forma de saber se uma função faz mais de “uma coisa” é se você pode extrair outra função dela a partir de seu nome que não seja apenas uma reformulação de sua implementação.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Seções Dentro de Funções
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Se temos seções, como declarações, inicializações, é um sinal de está fazendo mais de uma coisa;&lt;/li&gt;
&lt;li&gt;Não dá para dividir em seções as funções que fazem apenas uma coisa.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Um Nível de Abstração por Função
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Vários níveis dentro de uma função sempre geram confusão.&lt;/li&gt;
&lt;li&gt;Leitores podem não conseguir dizer se uma expressão determinada é um conceito essencial ou um mero detalhe.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Ler o Código de Cima para Baixo: Regra Decrescente
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Queremos que o código seja lido de cima para baixo, como uma narrativa.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Regra Decrescente&lt;/strong&gt;: Cada função seja seguida pelas outras no próximo nível de modo que possamos ler o programa descendo um nível de cada vez conforme percorremos a lista de funções.&lt;/li&gt;
&lt;li&gt;Acaba sendo muito difícil para programadores aprenderem a seguir essa regra e criar funções que fiquem em apenas um nível.&lt;/li&gt;
&lt;li&gt;É muito importante aprender esse truque, pois ele é o segredo para manter funções curtas e garantir que façam apenas “uma coisa”.&lt;/li&gt;
&lt;li&gt;Fazer com que a leitura do código possa ser feita de cima para baixo como uma série de parágrafos ”TO” é uma técnica eficiente para manter o nível consistente.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Estrutura Switch
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;É difícil criar uma estrutura &lt;code&gt;switch&lt;/code&gt; pequena;&lt;/li&gt;
&lt;li&gt;Também é difícil criar uma que faça apenas uma coisa.&lt;/li&gt;
&lt;li&gt;Por padrão, os &lt;code&gt;switch&lt;/code&gt; sempre fazem muitas coisas.&lt;/li&gt;
&lt;li&gt;Mas podemos nos certificar se cada um está em uma classe de baixo nível e nunca é repetido, usando o polimorfismo.&lt;/li&gt;
&lt;li&gt;A seguinte função mostra apenas uma das operações que podem depender do tipo de funcionário:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public Money calculatePay(Employee e) throws InvalidEmployeeType {
    switch (e.type) {
        case COMMISSIONED:
            return calculateCommissionedPay(e);
        case HOURLY:
            return calculateHourlyPay(e);
        case SALARIED:
            return calculateSalariedPay(e);
        default:
            throw new InvalidEmployeeType(e.type);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Essa função acima tem vários problemas:

&lt;ul&gt;
&lt;li&gt;Primeiro: Ela é grande, e quando adicionarmos novos tipos de funcionários ela crescerá mais ainda;&lt;/li&gt;
&lt;li&gt;Segundo: Ela faz mais de uma coisa;&lt;/li&gt;
&lt;li&gt;Terceiro: Ela viola o Princípio da Responsabilidade Única (SRP - SOLID) por haver mais de um motivo para alterá-la;&lt;/li&gt;
&lt;li&gt;Quarto: Ela viola o Princípio de Aberto-Fechado (OCP - SOLID), porque ela precisa ser modificada sempre que novos tipos forem adicionados;&lt;/li&gt;
&lt;li&gt;E possivelmente o pior problema é a quantidade ilimitada de outras funções que terão a mesma estrutura, por exemplo:
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;isPayday(Employee e, Date date),
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ou&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;deliverPay(Employee e, Money pay),
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;A solução nesse caso é inserir uma estrutura switch no fundo de uma ABSTRACT FACTORY:

&lt;ul&gt;
&lt;li&gt;Assim, a factory usará o &lt;code&gt;switch&lt;/code&gt; para criar instâncias apropriadas derivadas de Employee;&lt;/li&gt;
&lt;li&gt;As funções: &lt;code&gt;calculatePay&lt;/code&gt;, &lt;code&gt;isPayday&lt;/code&gt; e &lt;code&gt;deliverPay&lt;/code&gt;, serão enviadas de forma polifórmica através da interface &lt;code&gt;Employee&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;A regra geral para estruturas &lt;code&gt;switch&lt;/code&gt; é que são aceitáveis se aparecerem apenas uma vez para a criação de objetos polimórficos, e se estiverem escondidas atrás de uma relação de herança de modo que o resto do sistema não possa enxergá-la. Mas cada caso é um caso e podem haver casos de não respeitar todas essas regras.&lt;/li&gt;
&lt;li&gt;Assim temos como solução o seguinte código:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public abstract class Employee {
    public abstract boolean isPayday();
    public abstract Money calculatePay();
    public abstract void deliverPay(Money pay);
}
-----------------
public interface EmployeeFactory {
    public Employee makeEmployee(EmployeeRecord r) throws InvalidEmployeeType;
}
-----------------
public class EmployeeFactoryImpl implements EmployeeFactory {
    public Employee makeEmployee(EmployeeRecord r) throws InvalidEmployeeType {
        switch (r.type) {
            case COMMISSIONED:
                return new CommissionedEmployee(r) ;
            case HOURLY:
                return new HourlyEmployee(r);
            case SALARIED:
                return new SalariedEmploye(r);
            default:
                throw new InvalidEmployeeType(r.type);
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Use Nomes Descritivos
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;É muito importante ter bons nomes;&lt;/li&gt;
&lt;li&gt;Lembre-se do princípio de Ward: “Você sabe que está criando um código limpo quando cada rotina que você lê é como você esperava”;

&lt;ul&gt;
&lt;li&gt;Metade do esforço para satisfazer esse princípio é escolher bons nomes para funções pequenas que fazem apenas uma coisa.&lt;/li&gt;
&lt;li&gt;Quanto menor e mais centralizada é a função, mais fácil é pensar em um nome descritivo.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Não tenha medo de criar nomes extensos, pois eles são melhores do que um pequeno e enigmático. Um nome longo e descritivo é melhor do que um comentário extenso e descritivo.&lt;/li&gt;
&lt;li&gt;Experimente diversos nomes até encontrar um que seja bem descritivo.&lt;/li&gt;
&lt;li&gt;Seja consistente nos nomes. Use as mesmas frases, substantivos e verbos nos nomes de funções de seu módulo.&lt;/li&gt;
&lt;li&gt;Exemplos:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;includeSetup-AndTeardownPages&lt;/code&gt;, &lt;code&gt;includeSetupPages&lt;/code&gt;, &lt;code&gt;includeSuiteSetupPage&lt;/code&gt; , e &lt;code&gt;includeSetupPage&lt;/code&gt;. &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Parâmetros de Funções
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A quantidade ideal de parâmetros para uma função é zero. Depois vem um, seguido de dois. Sempre que possível devem-se evitar três parâmetros. Para mais de três deve-se ter um motivo muito especial, mesmo assim não devem ser usados.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parâmetros são complicados&lt;/strong&gt;. Eles requerem bastante conceito.&lt;/li&gt;
&lt;li&gt;Os parâmetros são mais difíceis ainda a partir de um ponto de vista de testes:

&lt;ul&gt;
&lt;li&gt;Imagina a dificuldade de escrever todos os casos de testes para se certificar de que todas as várias combinações de parâmetros funcionem adequadamente.;&lt;/li&gt;
&lt;li&gt;Se não houver parâmetros, essa tarefa é simples;&lt;/li&gt;
&lt;li&gt;Se houver um, não é tão difícil assim;&lt;/li&gt;
&lt;li&gt;Com dois, a situação fica um pouco desafiadora. Com mais de dois, pode ser desencorajador testar cada combinação de valores apropriados.&lt;/li&gt;
&lt;li&gt;Os parâmetros de saída são mais difíceis de entender do que os de entrada.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Por fim, um parâmetro de entrada é a melhor coisa depois de zero parâmetro!&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Formas Monádicas (Um parâmetro) Comuns
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Duas razões para se passar um único parâmetro a uma função:

&lt;ul&gt;
&lt;li&gt;Você pode estar fazendo uma pergunta sobre aquele parâmetro, exemplo: &lt;code&gt;boolean fileExists(“MyFile”’)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Ou você pode trabalhar parâmetro, transformando-o em outra coisa e retornando-o, exemplo: &lt;code&gt;InputStream fileOpen(“MyFile”)&lt;/code&gt; transforma a &lt;code&gt;String&lt;/code&gt; do nome de um arquivo em um valor retornado por InputStream.&lt;/li&gt;
&lt;li&gt;Outro uso menos comum é para uma função de evento, neste caso há um parâmetro de entrada, mas nenhum de saída. Cuidado ao usar essa abordagem!&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Se uma função vai transformar seu parâmetro de entrada, a alteração deve aparecer como o valor retornado. Por exemplo:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;StringBuffer transform(StringBuffer in)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;É melhor do que:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void transform(StringBuffer out)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Parâmetros Lógicos
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Esses parâmetros são feios.&lt;/li&gt;
&lt;li&gt;Passar um booleano para uma função certamente é uma prática horrível, pois ele complica imediatamente a assinatura do método, mostrando explicitamente que a função faz mais de uma coisa.&lt;/li&gt;
&lt;li&gt;Ela faz uma coisa se o valor for verdadeiro, e outra se for falso!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Funções Díades (Dois parâmetros)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;“Uma função com um parâmetro é mais difícil de entender do que com um”.&lt;/li&gt;
&lt;li&gt;Com dois parâmetros, é preciso aprender a ignorar um dos parâmetros, porém o local que ignoramos é justamente onde os bugs se esconderão.&lt;/li&gt;
&lt;li&gt;Casos em dois parâmetros são necessários:

&lt;ul&gt;
&lt;li&gt;Por exemplo, uma classe com eixos cartesianos, como por exemplo, &lt;code&gt;Point p = new Point(0, 0)&lt;/code&gt;, é preciso ter os dois parâmetros;&lt;/li&gt;
&lt;li&gt;Nesse caso os dois parâmetros &lt;strong&gt;são componentes de um único valor&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Mesmo funções óbvias como &lt;code&gt;assertEquals(expected, actual)&lt;/code&gt;, são problemáticas!&lt;/li&gt;
&lt;li&gt;Quantas vezes já colocou &lt;code&gt;actual&lt;/code&gt; on deveria ser &lt;code&gt;expected&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;Os dois parâmetros não possuem uma ordem pré-determinada natural;&lt;/li&gt;
&lt;li&gt;A ordem &lt;code&gt;expected&lt;/code&gt;, &lt;code&gt;actual&lt;/code&gt; é uma convenção que requer prática para assimilá-la.&lt;/li&gt;
&lt;li&gt;Funções com dois parâmetros &lt;strong&gt;não são ruins&lt;/strong&gt; e vamos usá-las!&lt;/li&gt;
&lt;li&gt;Mas devemos tentar converter essas funções em funções de um parâmetro, usando outro método ou variáveis de classe ou ainda outra classe que recebe o parâmetro no construtor.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tríades (Três parâmetros)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;São consideravelmente mais difíceis de entender do que as com dois parâmetros;&lt;/li&gt;
&lt;li&gt;Pense bastante antes de criar uma tríade!&lt;/li&gt;
&lt;li&gt;O processo de ordenação, pausa e ignoração apresenta mais do que o dobro de dificuldade.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Objetos como parâmetro
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;“Quando uma função parece precisar de mais de dois parâmetros, é provável que alguns desses parâmetros devam ser agrupados em uma classe própria”. Por exemplo:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Circle makeCircle(double x, double y, double radius);
Circle makeCircle(Point center, double radius);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Criar objetos para reduzir o número de parâmetros pode parecer trapaça, mas não é.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Listas como parâmetro
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Quando queremos passar um número variável de parâmetros para uma função, como por exemplo:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;String.format("%s worked %.2f hours.", name, hours);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Se os parâmetros forem todos tratados da mesma forma, eles serão equivalentes a um único parâmetro do tipo &lt;code&gt;List&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Por isso, o &lt;code&gt;String.format&lt;/code&gt; é uma função com dois parâmetros:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public String format(String format, Object... args)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Verbos e palavras-chave
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Escolher bons nomes para uma função pode ajudar muito a explicar a intenção da função e a ordem e a intenção dos parâmetros.&lt;/li&gt;
&lt;li&gt;No caso de função com um parâmetro, a função e o parâmetro devem formar um par verbo/substantivo muito bom. Por exemplo, &lt;code&gt;write(name)&lt;/code&gt;, qualquer que seja essa coisa “name” está sendo “write” (escrito). Um nome ainda melhor poderia ser &lt;code&gt;writeField(name)&lt;/code&gt;, que indica que o “name” é um campo.&lt;/li&gt;
&lt;li&gt;Por exemplo: &lt;code&gt;assertEquals&lt;/code&gt; pode ser melhor escrito como &lt;code&gt;assertExpectedEqualsActual(expected, actual)&lt;/code&gt;, assim diminui o problema de ter que lembrar a ordem dos parâmetros.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Evite Efeitos Colaterais
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;“Efeitos colaterais são mentiras”.&lt;/li&gt;
&lt;li&gt;Se a função promete fazer apenas uma coisa, mas também faz outras coisas escondidas. Vamos ter efeitos indesejáveis. Por exemplo:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class UserValidator {
    private Cryptographer cryptographer;

    public boolean checkPassword(String userName, String password) {
        User user = UserGateway.findByName(userName);
        if (user != User.NULL) {
            String codedPhrase = user.getPhraseEncodedByPassword();
            String phrase = cryptographer.decrypt(codedPhrase, password);
            if ("Valid Password".equals(phrase)) {
                Session.initialize();
                return true;
            }
        }
        return false;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Essa função de verificar a senha, tem um efeito colateral, que é a chamada do &lt;code&gt;Session.initialize()&lt;/code&gt;, o nome &lt;code&gt;checkPassword&lt;/code&gt; indica que verifica a senha, mas não indica que também inicializa a sessão. Assim, podemos correr o risco de apagar os dados da sessão existente quando ele decidir autenticar o usuário.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Assim, temos um efeito colateral de acoplamento. No caso o &lt;code&gt;checkPassword&lt;/code&gt; só pode ser chamada quando realmente formos inicializar a sessão, do contrário dados serão perdidos.&lt;/li&gt;
&lt;li&gt;Se realmente queremos manter o acoplamento dessa forma, deveríamos deixar explícito no nome da função, como por exemplo, &lt;code&gt;checkPasswordAndInitializeSession&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Parâmetros de Saída
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Quando precisamos reler a assinatura da função para entender o que acontece com o parâmetro de entrada, temos um problema, e isso deve ser evitado!&lt;/li&gt;
&lt;li&gt;De modo geral, devemos evitar parâmetros de saída. Caso a função precise alterar o estado de algo, mude o estado do objeto que a pertence.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Separação comando-consulta
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;As funções &lt;strong&gt;devem fazer ou responder algo, mas não ambos&lt;/strong&gt;. Ou alterar o estado de um objeto ou retorna informações sobre ele.&lt;/li&gt;
&lt;li&gt;Fazer as duas tarefas costuma gerar confusão. Por exemplo:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public boolean set(String attribute, String value);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pode levar a instruções estranhas como:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (set("username", "unclebob"))...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E fica um &lt;strong&gt;caos a interpretação&lt;/strong&gt;, o que significa esse trecho de código, estamos perguntando se o atributo “username” recebeu o valor “unclebob”? Ou se “username” obteve êxito ao receber o valor “unclebob”?&lt;br&gt;
A intenção neste código acima é ter o &lt;code&gt;set&lt;/code&gt; como um adjetivo, assim deveríamos ler “se o atributo &lt;code&gt;username&lt;/code&gt; anteriormente recebeu o valor &lt;code&gt;unclebob&lt;/code&gt;, porém não fica bem claro, para isso devemos usar o nome melhor como &lt;code&gt;setAndCheckIfExists&lt;/code&gt;, mesmo assim ainda tinhamos um código estranho:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (attributeExists("username")) {
setAttribute("username", "unclebob");
...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Prefira exceções a retorno de códigos de erro
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Fazer funções retornarem códigos de erros é uma leve violação da separação comando-consulta, pois os comandos são usados como expressões de comparação em estruturas &lt;code&gt;if&lt;/code&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (deletePage(page) == E_OK)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Retornar código de erro se torna um problema para quem chama a função, já que ele vai ter que lidar com o erro e possivelmente criar estruturas aninhadas, deixando o código muito ruim.&lt;/li&gt;
&lt;li&gt;Mas se usarmos exceções, o código de tratamento de erro pode ficar separado do código e ser simplificado, por exemplo:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;try {
    deletePage(page);
    registry.deleteReference(page.name);
    configKeys.deleteKey(page.name.makeKey());
}
catch (Exception e) {
    logger.log(e.getMessage());
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Extraia os blocos try/catch

&lt;ul&gt;
&lt;li&gt;Esses blocos não tem o direito de serem feios;&lt;/li&gt;
&lt;li&gt;Eles confundem a estrutura do código e misturam o tratamento de erro com o processamento normal do código;&lt;/li&gt;
&lt;li&gt;É melhor colocar esses blocos em suas próprias funções:
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public void delete(Page page) {
    try {
        deletePageAndAllReferences(page);
    }
    catch (Exception e) {
        logError(e);
    }
}

private void deletePageAndAllReferences(Page page) throws Exception {
    deletePage(page);
    registry.deleteReference(page.name);
    configKeys.deleteKey(page.name.makeKey());
}

private void logError(Exception e) {
    logger.log(e.getMessage());
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assim, a função &lt;code&gt;delete&lt;/code&gt; só faz o tratamento de erro, a função &lt;code&gt;deletePageAndAllReferences&lt;/code&gt; só trata de processos que excluem toda página, e o log apenas adicionar a mensagem do erro no console.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tratamento de erro é uma coisa só
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Tratamento de erro é uma coisa só, portanto uma função que trata erros não deve fazer mais nada!&lt;/li&gt;
&lt;li&gt;Assim, a instrução &lt;code&gt;try&lt;/code&gt; deve ser a primeira instrução da função e nada mais antes dela.&lt;/li&gt;
&lt;li&gt;Assim, podemos evitar o uso de classe de erros como por exemplo &lt;code&gt;Error.java&lt;/code&gt;, sendo um Enum como vários erros e que tudo dependeria dessa classe.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Evite repetição
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Repetição é um problema.&lt;/li&gt;
&lt;li&gt;Sempre será necessário modificar mais de um lugar quando o algoritmo mudar.&lt;/li&gt;
&lt;li&gt;E nisso podemos omitir erros gerando bugs.&lt;/li&gt;
&lt;li&gt;A duplicação pode ser a raiz de todo o mal no software.&lt;/li&gt;
&lt;li&gt;Muitos princípios e práticas têm sido criadas com a finalidade de controlar ou eliminar a repetição de código.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Programação estruturada
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Programação estruturada de Edsger Dijkstra: “Cada função e bloco dentro de uma função deve ter uma entrada e uma saída”.&lt;/li&gt;
&lt;li&gt;Apenas em funções maiores tais regras proporcionam benefícios significativos.&lt;/li&gt;
&lt;li&gt;Se mantivermos funções pequenas, as várias instruções &lt;code&gt;return, break, continue&lt;/code&gt; não trarão problemas.
Mas instruções como &lt;code&gt;goto&lt;/code&gt; só devem existir em grandes funções e devemos evitá-las.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Como escrever funções como essa?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Talvez não seja possível aplicar todas as regras vistas até aqui de início.&lt;/li&gt;
&lt;li&gt;Nas funções, elas começam longas e complexas, com muitos níveis de indentações e loops aninhados, muitos parâmetros, nomes ruins e aleatórios, duplicação de código. &lt;/li&gt;
&lt;li&gt;Porém depois organizamos, refinamos o código, dividindo em funções, trocamos os os nomes, removemos a duplicação, e no fim devemos ter uma função que respeite as regras vistas aqui.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;As funções são os verbos e as classes os substantivos.&lt;/li&gt;
&lt;li&gt;“Essa é uma verdade muito antiga”.&lt;/li&gt;
&lt;li&gt;“A arte de programar é, e sempre foi, a arte do projeto de linguagem” (linguagem literal, narrativa).&lt;/li&gt;
&lt;li&gt;Seguindo as regras deste capítulo, suas funções serão curtas, bem nomeadas e bem organizadas.&lt;/li&gt;
&lt;li&gt;“Mas jamais se esqueça de que seu objetivo verdadeiro é contar a história do sistema”.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>books</category>
      <category>codequality</category>
    </item>
    <item>
      <title>Novo projeto React Native usando ESLint e Prettier</title>
      <dc:creator>Jonilson Sousa</dc:creator>
      <pubDate>Wed, 05 May 2021 15:01:45 +0000</pubDate>
      <link>https://dev.to/jonilsonds9/novo-projeto-react-native-usando-eslint-e-prettier-2op9</link>
      <guid>https://dev.to/jonilsonds9/novo-projeto-react-native-usando-eslint-e-prettier-2op9</guid>
      <description>&lt;p&gt;Esse é basicamente um passo a passo de como podemos criar um projeto React Native e adicionar o ESLint e Prettier e ainda executar em um dispositivo físico!&lt;/p&gt;

&lt;h3&gt;
  
  
  Extensões e criação do projeto
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Instale as extensões do ESLint e do Prettier no seu VS Code primeiro.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Crie um novo projeto React Native com o comando:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx react-native init NomeDoProjeto
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Agora entre dentro da pasta do projeto:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd NomeDoProjeto
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Abra o VS Code e &lt;strong&gt;apague&lt;/strong&gt; o arquivo &lt;code&gt;.eslintrc.js&lt;/code&gt;, queremos criar outro usando o ESLint.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Volte ao terminal e configure o ESLint para isso execute o comando:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx eslint --init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;E escolha as opções:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;How would you like to use ESLint?
  To check syntax only
  To check syntax and find problems
❯ To check syntax, find problems, and enforce code style (use está opção)

-----------------------------------------------

What type of modules does your project use?
❯ JavaScript modules (import/export) (use está opção)
  CommonJS (require/exports)
  None of these

-----------------------------------------------

Which framework does your project use? (Use arrow keys)
❯ React (use está opção)
  Vue.js
  None of these

----------------------------------------------------

Does your project use TypeScript? · No / Yes (responda não)

----------------------------------------------------

Where does your code run? · No items were selected (deixe em branco, apenas tecle ENTER)

----------------------------------------------------

How would you like to define a style for your project? (Use arrow keys)
❯ Use a popular style guide (use está opção)
  Answer questions about your style
  Inspect your JavaScript file(s)

----------------------------------------------------

Which style guide do you want to follow? (Use arrow keys)
❯ Airbnb (https://github.com/airbnb/javascript) (use está opção)
  Standard (https://github.com/standard/standard)
  Google (https://github.com/google/eslint-config-google)

----------------------------------------------------

What format do you want your config file to be in? (Use arrow keys)
❯ JavaScript (use está opção)
  YAML
  JSON

----------------------------------------------------

Would you like to install them now with npm? (Y/n) : Y (responda Y e espere ele instalar as dependências)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Após esse processo ele deve ter criado um novo arquivo &lt;code&gt;.eslintrc.js&lt;/code&gt;, devemos deixá-lo com o seguinte conteúdo:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.exports = {
  env: {
    es2021: true,
  },
  extends: ['airbnb', 'plugin:react/recommended', 'prettier'],
  parserOptions: {
    ecmaFeatures: {
      jsx: true,
    },
    ecmaVersion: 12,
    sourceType: 'module',
  },
  plugins: ['react', 'prettier'],
  rules: {
    'prettier/prettier': 'error',
    'react/jsx-filename-extension': [
      'warn',
      {
        extensions: ['.jsx', '.js'],
      },
    ],
    'import/prefer-default-export': 'off',
    'react/state-in-constructor': 'off',
    'react/static-property-placement': 'off',
    'react/jsx-props-no-spreading': 'off',
    'react/prop-types': 'off',
    'no-param-reassign': 'off',
    'no-console': 'off',
  },
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Agora podemos instalar o &lt;code&gt;prettier&lt;/code&gt; com o comando:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --save-dev --save-exact prettier
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Também devemos instalar o plugin &lt;code&gt;eslint-config-prettier&lt;/code&gt; para que o ESLint e Prettier possam funcionar sem conflitos:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --save-dev --save-exact eslint-config-prettier
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lembrando que devemos a seguinte linha no arquivo de configuração do ESLint &lt;code&gt;.eslintrc.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;extends: ['airbnb', 'plugin:react/recommended', 'prettier'],
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso garante que não vamos ter conflitos entre ambos e podemos ter as sugestṍes de códigos do prettier, então teremos o ESLint indicando os erros e o prettier executando a correção se clicarmos com o botão direito do mouse.&lt;br&gt;
Podemos deixar o arquivo de configuração do prettier (&lt;code&gt;.prettierrc.js&lt;/code&gt;) padrão:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.exports = {
  bracketSpacing: false,
  jsxBracketSameLine: true,
  singleQuote: true,
  trailingComma: 'all',
  arrowParens: 'avoid',
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Alterar as configurações do VS code
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Acesse o arquivo de preferências do VS Code como &lt;code&gt;json&lt;/code&gt;, você pode usar a palheta com o atalho Ctrl + Shift + P e digitar o nome "preferências", deve aparecer uma opção pra abrir como JSON &lt;code&gt;Open Settings (JSON)&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nesse arquivos devemos adicionar as seguintes configurações:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// parte do Prettier:
    "editor.defaultFormatter": "esbenp.prettier-vscode",
    "[javascript]": {
        "editor.defaultFormatter": "esbenp.prettier-vscode"
    },
    "editor.formatOnSave": true,

    // parte do ESLint:
    "editor.renderLineHighlight": "gutter",
    "emmet.syntaxProfiles": {
        "javascript": "jsx",
    },
    "emmet.includeLanguages": {
        "javascript": "javascriptreact"
    },
    "javascript.updateImportsOnFileMove.enabled": "never",
    "breadcrumbs.enabled": true,
    "editor.parameterHints.enabled": true,

    "eslint.autoFixOnSave": true,
    "editor.codeActionsOnSave": { "source.fixAll.eslint": true },
    "eslint.validate": [
        {
            "language": "javascript",
            "autoFix": true,
        },
        {
            "language": "javascriptreact",
            "autoFix": true,
        },
        {
            "language": "typescript",
            "autoFix": true,
        },
        {
            "language": "typescriptreact",
            "autoFix": true,
        },
    ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Executar o projeto no dispositivo
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Agora para executar o projeto, adicione o celular pelo cabo USB;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Para ver se o celular está conectado corretamente, use o comando:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;adb devices
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Veja o nome do dispositivo no comando acima, e depois execute o seguinte comando:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;adb -s &amp;lt;nome do device&amp;gt; reverse tcp:8081 tcp:8081
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Abra dois terminais, no primeiro execute o comando:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esse comando vai iniciar o bundle, para que ele faça o reload da aplicação no dispositivo.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No outro terminal instale a aplicação do App no dispositivo usando o comando:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx react-native run-android
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>reactnative</category>
      <category>codequality</category>
      <category>configs</category>
    </item>
  </channel>
</rss>
