<?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: William Koller</title>
    <description>The latest articles on DEV Community by William Koller (@williamkoller).</description>
    <link>https://dev.to/williamkoller</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%2F235349%2F9b4cbb6c-f6db-4d7b-b861-775616eaca11.jpeg</url>
      <title>DEV Community: William Koller</title>
      <link>https://dev.to/williamkoller</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/williamkoller"/>
    <language>en</language>
    <item>
      <title>O que é um ArrayList?</title>
      <dc:creator>William Koller</dc:creator>
      <pubDate>Tue, 18 Mar 2025 16:47:31 +0000</pubDate>
      <link>https://dev.to/williamkoller/o-que-e-um-arraylist-k88</link>
      <guid>https://dev.to/williamkoller/o-que-e-um-arraylist-k88</guid>
      <description>&lt;p&gt;O &lt;code&gt;ArrayList&lt;/code&gt; é uma estrutura de dados baseada em arrays que permite adicionar, remover e acessar elementos de forma eficiente. Diferente dos arrays tradicionais, o &lt;code&gt;ArrayList&lt;/code&gt; cresce dinamicamente conforme novos elementos são adicionados.&lt;/p&gt;

&lt;p&gt;Implementação do ArrayList em TypeScript&lt;/p&gt;

&lt;p&gt;Abaixo está a implementação completa de um ArrayList genérico em TypeScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export class ArrayList&amp;lt;T&amp;gt; {
  private items: T[];
  private map: Map&amp;lt;string, T&amp;gt;;

  constructor(initialCapacity: number = 0) {
    this.items = new Array&amp;lt;T&amp;gt;(initialCapacity);
    this.map = new Map&amp;lt;string, T&amp;gt;();
  }

  add(element: T): void {
    this.items.push(element);
  }

  addAll(elements: T[]): void {
    this.items.push(...elements);
  }

  get(index: number): T | undefined {
    if (index &amp;lt; 0 || index &amp;gt;= this.items.length) {
      throw new Error('Index out of bounds');
    }
    return this.items[index];
  }

  set(index: number, element: T): void {
    if (index &amp;lt; 0 || index &amp;gt;= this.items.length) {
      throw new Error('Index out of bounds');
    }
    this.items[index] = element;
  }

  remove(index: number): T | undefined {
    if (index &amp;lt; 0 || index &amp;gt;= this.items.length) {
      throw new Error('Index out of bounds');
    }
    return this.items.splice(index, 1)[0];
  }

  removeElement(element: T): boolean {
    const index = this.items.indexOf(element);
    if (index !== -1) {
      this.items.splice(index, 1);
      return true;
    }
    return false;
  }

  size(): number {
    return this.items.length;
  }

  isEmpty(): boolean {
    return this.items.length === 0;
  }

  contains(element: T): boolean {
    return this.items.includes(element);
  }

  clear(): void {
    this.items = [];
  }

  toArray(): T[] {
    return [...this.items];
  }

  indexOf(element: T): number {
    return this.items.indexOf(element);
  }

  lastIndexOf(element: T): number {
    return this.items.lastIndexOf(element);
  }

  subList(fromIndex: number, toIndex: number): T[] {
    if (fromIndex &amp;lt; 0 || toIndex &amp;gt; this.items.length || fromIndex &amp;gt; toIndex) {
      throw new Error('Index out of bounds');
    }
    return this.items.slice(fromIndex, toIndex);
  }

  forEach(callback: (element: T, index: number) =&amp;gt; void): void {
    this.items.forEach(callback);
  }

  sort(compareFn?: (a: T, b: T) =&amp;gt; number): void {
    this.items.sort(compareFn);
  }

  setKeyValue(key: string, value: T): void {
    this.map.set(key, value);
  }

  getValue(key: string): T | undefined {
    return this.map.get(key);
  }

  removeKey(key: string): boolean {
    return this.map.delete(key);
  }

  hasKey(key: string): boolean {
    return this.map.has(key);
  }

  clearMap(): void {
    this.map.clear();
  }

  mapSize(): number {
    return this.map.size;
  }
}

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

&lt;/div&gt;



&lt;p&gt;Explicação dos Métodos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;add(element: T): Adiciona um elemento à lista.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;addAll(elements: T[]): Adiciona múltiplos elementos de uma vez.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;get(index: number): Retorna o elemento em um índice específico.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;set(index: number, element: T): Atualiza o elemento em um índice.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;remove(index: number): Remove um elemento pelo índice.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;removeElement(element: T): Remove um elemento específico.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;size(): Retorna o tamanho atual da lista.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;isEmpty(): Verifica se a lista está vazia.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;contains(element: T): Verifica se um elemento está presente na lista.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;clear(): Remove todos os elementos da lista.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;toArray(): Retorna a lista como um array.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;indexOf(element: T): Retorna o índice da primeira ocorrência do elemento.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;lastIndexOf(element: T): Retorna o índice da última ocorrência do elemento.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;subList(fromIndex: number, toIndex: number): Retorna uma sublista entre os índices fornecidos.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;forEach(callback): Itera sobre os elementos da lista.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;sort(compareFn): Ordena os elementos com base em uma função opcional de comparação.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Exemplo de Uso:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const list = new ArrayList&amp;lt;number&amp;gt;();
list.add(10);
list.add(20);
list.add(30);
console.log(list.get(1)); // Saída: 20
list.remove(1);
console.log(list.toArray()); // Saída: [10, 30]

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

&lt;/div&gt;



&lt;p&gt;Repo no Github: &lt;a href="https://github.com/williamkoller/array-list" rel="noopener noreferrer"&gt;https://github.com/williamkoller/array-list&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Essa implementação do ArrayList em TypeScript oferece uma alternativa flexível para manipular listas dinâmicas de maneira eficiente. O uso de tipagem genérica permite que a lista funcione com qualquer tipo de dado, tornando-a extremamente versátil.&lt;/p&gt;

&lt;p&gt;Se gostou do artigo, compartilhe com outros desenvolvedores! 🚀&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>Ddd Python</title>
      <dc:creator>William Koller</dc:creator>
      <pubDate>Sat, 01 Feb 2025 02:45:05 +0000</pubDate>
      <link>https://dev.to/williamkoller/ddd-python-4hel</link>
      <guid>https://dev.to/williamkoller/ddd-python-4hel</guid>
      <description></description>
      <category>python</category>
    </item>
    <item>
      <title>SOLID - Princípios da Programação Orientada a Objetos (OOP)</title>
      <dc:creator>William Koller</dc:creator>
      <pubDate>Thu, 08 Aug 2024 14:35:07 +0000</pubDate>
      <link>https://dev.to/williamkoller/solid-principios-da-programacao-orientada-a-objetos-oop-50g3</link>
      <guid>https://dev.to/williamkoller/solid-principios-da-programacao-orientada-a-objetos-oop-50g3</guid>
      <description>&lt;h2&gt;
  
  
  Princípios de Design
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Bons sistemas de software começam com um código limpo. Por um lado, se os tijolos não são bem-feitos, a arquitetura de construção perde a importância. Por outro lado, você pode fazer uma bagunça considerável com tijolos bem-feitos. É aí que entra, os princípios SOLID - Robert C. Martin&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Os princípios SOLID orientam a organização das funções e estruturas de dados de uma classe e como essas classes devem ser interconectadas. O uso do termo 'classe' não limita a aplicação dos princípios apenas a softwares orientados a objetos; qualquer agrupamento acoplado de funções e dados em um sistema de software pode se beneficiar deles. O objetivo dos princípios SOLID é criar estruturas de software de nível médio que:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tolerem mudanças,&lt;/li&gt;
&lt;li&gt;Sejam fáceis de entender,&lt;/li&gt;
&lt;li&gt;Sirvam como base para componentes reutilizáveis em muitos sistemas de software.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  História
&lt;/h2&gt;

&lt;p&gt;A história dos princípios SOLID é extensa. No final dos anos 1980, foram discutidos em reuniões sobre princípios de design com participantes da USENET (um precursor das redes sociais modernas). Ao longo dos anos, os princípios evoluíram: alguns foram eliminados, outros mesclados ou adicionados. O conjunto final se estabilizou no início dos anos 2000, embora a ordem de apresentação tenha variado. Em 2004, Michael Feathers formalizou os princípios em um e-mail, observando que, se Robert C. Martin reorganizasse os princípios, suas iniciais formariam a palavra SOLID - e assim nasceram os princípios SOLID.&lt;/p&gt;

&lt;p&gt;Iremos falar cada palavra SOLID, abaixo.&lt;/p&gt;

&lt;h3&gt;
  
  
  SRP: Princípio de Responsabilidade Única (Single Responsability Principle)
&lt;/h3&gt;

&lt;p&gt;O Princípio de Responsabilidade Única (SRP) afirma que uma classe deve ter apenas uma razão para mudar, ou seja, ela deve ter apenas uma responsabilidade ou tarefa. Isso significa que cada classe deve focar em uma única parte da funcionalidade do software, sendo responsável apenas por uma parte do comportamento do sistema. Isso facilita a manutenção, testes e entendimento do código, além de melhorar a coesão e reduzir o acoplamento entre as partes do sistema.&lt;/p&gt;

&lt;h3&gt;
  
  
  OCP: O Princípio de Aberto/Fechado (Open/Closed Principle)
&lt;/h3&gt;

&lt;p&gt;O Princípio de Aberto/Fechado (OCP) afirma que uma entidade de software (como uma classe, módulo ou função) deve estar aberta para extensão, mas fechada para modificação. Isso significa que o comportamento de uma classe pode ser estendido sem alterar seu código-fonte original. A ideia é permitir que novas funcionalidades sejam adicionadas ao sistema sem a necessidade de alterar o código existente, reduzindo o risco de introduzir novos bugs e facilitando a manutenção e evolução do software.&lt;/p&gt;

&lt;h3&gt;
  
  
  LSP: Princípoir de Substituição de Liskov (Liskob Substitution Principle)
&lt;/h3&gt;

&lt;p&gt;O Princípio de Substituição de Liskov (LSP) afirma que uma subclasse deve ser substituível por sua superclasse sem alterar o comportamento desejado do programa. Em outras palavras, objetos de uma classe derivada devem poder ser usados no lugar de objetos da classe base sem que o programa funcione de maneira incorreta. Isso garante que as subclasses preservem a integridade do sistema, respeitando o contrato estabelecido pela superclasse, o que facilita a reutilização e a manutenção do código.&lt;/p&gt;

&lt;h3&gt;
  
  
  ISP: Princípio de Segregação de Interface (Interface Segregation Principle)
&lt;/h3&gt;

&lt;p&gt;O Princípio de Segregação de Interface (ISP) afirma que uma classe não deve ser obrigada a implementar interfaces que não utiliza. Em vez de ter uma única interface grande, é melhor ter várias interfaces menores e específicas, para que as classes possam implementar apenas o que realmente precisam. Isso reduz o acoplamento entre componentes e aumenta a coesão, facilitando a manutenção e evolução do software.&lt;/p&gt;

&lt;h3&gt;
  
  
  DIP: Princípio da Inversão de Dependência (Dependency Inversion Principle)
&lt;/h3&gt;

&lt;p&gt;O Princípio da Inversão de Dependência (DIP) afirma que módulos de alto nível não devem depender de módulos de baixo nível, mas ambos devem depender de abstrações. Além disso, abstrações não devem depender de detalhes; os detalhes devem depender de abstrações. Isso significa que a estrutura do código deve ser orientada a interfaces ou classes abstratas, permitindo que a implementação concreta possa ser alterada sem afetar os módulos que utilizam essas abstrações. Isso promove um código mais flexível, reutilizável e de fácil manutenção.&lt;/p&gt;

&lt;p&gt;Iremos mostrar uns exemplos em código de cada palavra SOLID, abaixo.&lt;/p&gt;

&lt;h3&gt;
  
  
  SRP: Princípio de Responsabilidade Única (Single Responsability Principle)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Order {
  public items: Item[];

  constructor() {
    this.items = [];
  }

  addItem(item: Item) {
    this.items.push(item);
  }

  calculateTotal() {
    let total = 0;
    for (const item of this.items) {
      total += item.price;
    }
    return total;
  }
}

class Item {
  name: string;
  price: number;

  constructor(name: string, price: number) {
    this.name = name;
    this.price = price;
  }
}

class OrderPrinter {
  print(order: Order) {
    console.log('Order Details:');
    for (const item of order.items) {
      console.log(`- ${item.name}: $${item.price}`);
    }
    console.log(`Total: $${order.calculateTotal()}`);
  }
}

const order = new Order();
order.addItem(new Item('Shirt', 20)); // - Shirt: $20

order.addItem(new Item('Pants', 50)); // - Pants: $50

order.addItem(new Item('Shoes', 100)); // - Shoes: $100

order.addItem(new Item('Hat', 10)); // - Hat: $10

const orderPrinter = new OrderPrinter();
orderPrinter.print(order); // Total: $180
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O Princípio de Responsabilidade Única (SRP) estabelece que uma classe deve ter apenas uma razão para mudar, ou seja, deve possuir uma única responsabilidade ou tarefa.&lt;/p&gt;

&lt;h4&gt;
  
  
  Como o código respeita o SRP
&lt;/h4&gt;

&lt;h5&gt;
  
  
  Responsabilidade de Gerenciamento de Itens:
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A classe &lt;code&gt;Order&lt;/code&gt; tem uma responsabilidade clara: gerenciar os itens de um pedido.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;O método &lt;code&gt;addItem&lt;/code&gt; permite adicionar itens ao pedido. Sua única responsabilidade é modificar a lista de itens (&lt;code&gt;this.items&lt;/code&gt;) dentro do objeto &lt;code&gt;Order&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Responsabilidade de Cálculo do Total:
&lt;/h4&gt;

&lt;p&gt;O método &lt;code&gt;calculateTotal&lt;/code&gt; é responsável por calcular o total do pedido somando os preços dos itens na lista.&lt;br&gt;
Ele não está alterando o estado do objeto Order, apenas calculando e retornando um valor com base nos itens já existentes.&lt;/p&gt;

&lt;p&gt;Ambos os métodos (addItem e calculateTotal) estão diretamente relacionados à principal responsabilidade da classe Order, que é gerenciar os itens do pedido e realizar operações relacionadas a esses itens.&lt;br&gt;
Justificativa de Conformidade com o SRP&lt;br&gt;
Coesão: A classe Order possui alta coesão, já que todos os métodos e propriedades estão diretamente relacionados ao gerenciamento de um pedido.&lt;br&gt;
Facilidade de Mudança: Se houver uma mudança na forma como os itens são gerenciados ou como o total é calculado, essas mudanças serão confinadas a esta única classe. Por exemplo, se a lógica de cálculo do total mudar (por exemplo, descontos ou taxas), apenas o método calculateTotal precisa ser atualizado.&lt;br&gt;
Clareza: A classe Order é fácil de entender porque sua responsabilidade é única e bem definida. Qualquer desenvolvedor pode olhar para essa classe e compreender rapidamente que ela serve para gerenciar itens de um pedido e calcular o total desses itens.&lt;/p&gt;

&lt;p&gt;Portanto, a classe Order demonstra uma aplicação clara do Princípio de Responsabilidade Única (SRP), mantendo uma única responsabilidade e tornando o código mais fácil de manter, entender e modificar.&lt;/p&gt;
&lt;h3&gt;
  
  
  OCP: O Princípio de Aberto/Fechado (Open/Closed Principle)
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface Shape {
  calculateArea(): number;
}

class Rectangle implements Shape {
  private width: number;
  private height: number;

  constructor(width: number, height: number) {
    this.width = width;
    this.height = height;
  }

  calculateArea(): number {
    return this.width * this.height;
  }
}

class Circle implements Shape {
  private radius: number;

  constructor(radius: number) {
    this.radius = radius;
  }

  calculateArea(): number {
    return Math.PI * this.radius * this.radius;
  }
}

class AreaCalculator {
  private shapes: Shape[];

  constructor(shapes: Shape[]) {
    this.shapes = shapes;
  }

  calculateTotalArea(): number {
    let totalArea = 0;
    for (const shape of this.shapes) {
      totalArea += shape.calculateArea();
    }
    return totalArea;
  }
}

const rectangle = new Rectangle(5, 10);
const circle = new Circle(7);

const areaCalculator = new AreaCalculator([rectangle, circle]);
const totalArea = areaCalculator.calculateTotalArea();
console.log("Total area:", totalArea); // Total area: 203.93804002589985T
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;O Princípio de Aberto/Fechado (OCP) afirma que uma entidade de software deve estar aberta para extensão, mas fechada para modificação. Isso significa que o comportamento de uma classe pode ser estendido sem alterar seu código-fonte original.&lt;br&gt;
Como o código respeita o OCP&lt;br&gt;
Interface Shape:&lt;br&gt;
Define um contrato (calculateArea) que todas as formas (shapes) devem implementar. Isso permite que novas formas possam ser adicionadas sem modificar a interface ou as classes existentes.&lt;/p&gt;

&lt;p&gt;Classes Rectangle e Circle:&lt;br&gt;
Ambas implementam a interface Shape, fornecendo suas próprias implementações de calculateArea.&lt;br&gt;
Se quisermos adicionar uma nova forma (por exemplo, Triangle), podemos criar uma nova classe que implemente Shape sem modificar as classes Rectangle ou Circle.&lt;/p&gt;

&lt;p&gt;Classe AreaCalculator:&lt;br&gt;
Aceita uma lista de objetos que implementam a interface Shape.&lt;br&gt;
O método calculateTotalArea itera sobre essa lista e calcula a área total chamando calculateArea em cada forma.&lt;br&gt;
Se novas formas forem adicionadas, não é necessário modificar AreaCalculator, pois ela depende da abstração Shape.&lt;/p&gt;

&lt;p&gt;Justificativa de Conformidade com o OCP&lt;br&gt;
Extensibilidade: O design permite a adição de novas formas sem modificar o código existente. Para adicionar uma nova forma, basta criar uma nova classe que implemente a interface Shape.&lt;br&gt;
Evita Modificações: O código existente das classes Rectangle, Circle e AreaCalculator permanece inalterado quando novas formas são adicionadas, minimizando o risco de introdução de novos bugs.&lt;br&gt;
Uso de Abstrações: A classe AreaCalculator trabalha com a abstração Shape em vez de classes concretas, promovendo a flexibilidade e aderência ao OCP.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Triangle implements Shape {
  private base: number;
  private height: number;

  constructor(base: number, height: number) {
    this.base = base;
    this.height = height;
  }

  calculateArea(): number {
    return 0.5 * this.base * this.height;
  }
}

const triangle = new Triangle(10, 5);
const areaCalculatorWithTriangle = new AreaCalculator([rectangle, circle, triangle]);
const newTotalArea = areaCalculatorWithTriangle.calculateTotalArea();
console.log("New total area:", newTotalArea); // Calcula a área total incluindo o triângulo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como podemos ver, adicionar uma nova forma (Triangle) não requer nenhuma modificação nas classes Rectangle, Circle ou AreaCalculator, demonstrando claramente a aplicação do Princípio de Aberto/Fechado (OCP).&lt;/p&gt;

&lt;h3&gt;
  
  
  LSP: Princípoir de Substituição de Liskov (Liskob Substitution Principle)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;abstract class BaseNotification {
  abstract send(message: string): void;
}

class EmailNotification extends BaseNotification {
  constructor(private emailAddress: string) {
    super();
  }
  send(message: string): void {
    console.log(`Sending email to ${this.emailAddress}: ${message}`);
  }
}

class SMSNotification extends BaseNotification {
  constructor(private phoneNumber: string) {
    super();
  }

  send(message: string): void {
    console.log(`Sending SMS to ${this.phoneNumber}: ${message}`);
  }
}

class PushNotification extends BaseNotification {
  constructor(private deviceToken: string) {
    super();
  }

  send(message: string): void {
    console.log(`Sending push notification to ${this.deviceToken}: ${message}`);
  }
}

function notifyUser(baseNotification: BaseNotification, message: string) {
  baseNotification.send(message);
}

const emailNotification = new EmailNotification('user@example.com');
const smsNotification = new SMSNotification('123-456-7890');
const pushNotification = new PushNotification('device-token-123');

notifyUser(emailNotification, 'Your order has been shipped!'); // Sending email to user@example.com: Your order has been shipped!
notifyUser(smsNotification, 'Your order has been shipped!'); // Sending SMS to 123-456-7890: Your order has been shipped!
notifyUser(pushNotification, 'Your order has been shipped!'); // Sending push notification to device-token-123: Your order has been shipped!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O Princípio de Substituição de Liskov (LSP) afirma que uma subclasse deve ser substituível por sua superclasse sem alterar o comportamento desejado do programa. Em outras palavras, objetos de uma classe derivada devem poder ser usados no lugar de objetos da classe base sem que o programa funcione de maneira incorreta.&lt;br&gt;
Como o código respeita o LSP&lt;br&gt;
Classe Base Abstrata BaseNotification:&lt;br&gt;
Define o método abstrato send, que deve ser implementado por todas as subclasses.&lt;br&gt;
Fornece um contrato comum para todas as notificações, garantindo que qualquer tipo de notificação possa ser enviada usando o método send.&lt;/p&gt;

&lt;p&gt;Subclasses EmailNotification, SMSNotification e PushNotification:&lt;br&gt;
Cada uma dessas classes herda de BaseNotification e implementa o método send de forma específica para o tipo de notificação.&lt;br&gt;
Elas podem ser usadas de forma intercambiável no contexto de BaseNotification.&lt;/p&gt;

&lt;p&gt;Função notifyUser:&lt;br&gt;
Aceita um objeto de BaseNotification e uma mensagem, chamando o método send do objeto passado.&lt;br&gt;
Como todas as subclasses de BaseNotification implementam send, notifyUser pode aceitar qualquer uma das subclasses sem precisar de modificações.&lt;/p&gt;

&lt;p&gt;Justificativa de Conformidade com o LSP&lt;br&gt;
Substituibilidade: A função notifyUser pode receber qualquer instância de BaseNotification, seja ela EmailNotification, SMSNotification ou PushNotification, e chamará o método send sem problemas. Isso demonstra que as subclasses são substituíveis pela superclasse sem alterar o comportamento da função.&lt;br&gt;
Consistência de Comportamento: Cada subclasse implementa o método send de acordo com suas próprias necessidades, mas a interface de uso (BaseNotification) permanece consistente. Isso garante que o comportamento do programa não se altere ao substituir uma instância de BaseNotification por qualquer uma de suas subclasses.&lt;br&gt;
Polimorfismo: O uso de polimorfismo é evidente, pois a função notifyUser não precisa saber qual tipo específico de notificação está sendo enviada. Ela apenas chama send no objeto BaseNotification, confiando que o comportamento adequado será executado pela implementação concreta da subclasse.&lt;/p&gt;

&lt;p&gt;Adicionar uma nova forma de notificação, como SlackNotification, é simples e demonstra a conformidade com o LSP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class SlackNotification extends BaseNotification {
  constructor(private slackChannel: string) {
    super();
  }

  send(message: string): void {
    console.log(`Sending Slack message to ${this.slackChannel}: ${message}`);
  }
}

const slackNotification = new SlackNotification('#general');
notifyUser(slackNotification, 'Your order has been shipped!'); // Sending Slack message to #general: Your order has been shipped!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ISP: Princípio de Segregação de Interface (Interface Segregation Principle)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface PaymentService {
  processPayment(amount: number): void;
}

class CreditCardPaymentService implements PaymentService {
  processPayment(amount: number): void {
    console.log(`Processando pagamento de R$${amount} com cartão de crédito...`);
  }
}

class BoletoPaymentService implements PaymentService {
  processPayment(amount: number): void {
    console.log(`Processando pagamento de R$${amount} com boleto bancário...`);
  }
}

class Purchase {
  private paymentService: PaymentService;

  constructor(paymentService: PaymentService) {
    this.paymentService = paymentService;
  }

  processPurchase(amount: number): void {
    console.log(`Processando compra de R$${amount}...`);
    this.paymentService.processPayment(amount);
    console.log('Compra concluída!');
  }
}

const creditCardPaymentService = new CreditCardPaymentService(); // Processando pagamento de R$100 com cartão de crédito...
const purchaseWithCreditCard = new Purchase(creditCardPaymentService); // Processando compra de R$100...
purchaseWithCreditCard.processPurchase(100);

const boletoPaymentService = new BoletoPaymentService(); // Processando pagamento de R$200 com boleto bancário...
const purchaseWithBoleto = new Purchase(boletoPaymentService); // Processando compra de R$200...
purchaseWithBoleto.processPurchase(200);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O Princípio de Segregação de Interface (ISP) afirma que uma classe não deve ser obrigada a implementar interfaces que não utiliza. Isso significa que é melhor ter várias interfaces pequenas e específicas do que uma única interface grande e genérica, permitindo que as classes implementem apenas o que realmente precisam.&lt;br&gt;
Como o código respeita o ISP&lt;br&gt;
Interface PaymentService:&lt;br&gt;
Define um contrato específico para o serviço de pagamento com o método processPayment. Esta interface é pequena e focada, contendo apenas o que é necessário para o processamento de pagamentos.&lt;br&gt;
Como a interface é específica para pagamentos, as classes que a implementam não são forçadas a adicionar métodos desnecessários.&lt;/p&gt;

&lt;p&gt;Classes CreditCardPaymentService e BoletoPaymentService:&lt;br&gt;
Ambas implementam a interface PaymentService e fornecem sua própria implementação do método processPayment.&lt;br&gt;
Cada classe se concentra exclusivamente em como processar um tipo específico de pagamento (cartão de crédito ou boleto), mantendo a interface e a implementação focadas e coesas.&lt;/p&gt;

&lt;p&gt;Classe Purchase:&lt;br&gt;
Recebe uma instância de PaymentService e usa o método processPayment para processar o pagamento.&lt;br&gt;
Não precisa saber ou se preocupar com os detalhes de como o pagamento é processado; isso é abstraído pela interface PaymentService.&lt;/p&gt;

&lt;p&gt;Justificativa de Conformidade com o ISP&lt;br&gt;
Interfaces Pequenas e Específicas: A interface PaymentService é pequena e específica, focando apenas no que é necessário para o processamento de pagamentos. As classes CreditCardPaymentService e BoletoPaymentService implementam exatamente o que é exigido pela interface, sem adicionar métodos desnecessários.&lt;br&gt;
Não Forçado a Implementar Métodos Não Usados: As classes que implementam PaymentService não são forçadas a adicionar métodos que não são relevantes para o tipo específico de pagamento que elas processam. Isso evita que as classes se tornem complexas e difíceis de manter.&lt;br&gt;
Flexibilidade e Manutenção: O design permite adicionar novos tipos de serviços de pagamento no futuro (por exemplo, pagamentos via PayPal ou transferência bancária) simplesmente implementando a interface PaymentService. Não há necessidade de modificar a interface ou as classes existentes, mantendo o sistema flexível e fácil de manter.&lt;/p&gt;

&lt;p&gt;Exemplo de Extensão&lt;br&gt;
Se quisermos adicionar um novo método de pagamento, como PayPalPaymentService, podemos seguir o mesmo 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;class PayPalPaymentService implements PaymentService {
  processPayment(amount: number): void {
    console.log(`Processando pagamento de R$${amount} com PayPal...`);
  }
}

const payPalPaymentService = new PayPalPaymentService();
const purchaseWithPayPal = new Purchase(payPalPaymentService);
purchaseWithPayPal.processPurchase(300); // Processando compra de R$300... Processando pagamento de R$300 com PayPal... Compra concluída!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  DIP: Princípio da Inversão de Dependência (Dependency Inversion Principle)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import nodemailer from 'nodemailer';
import { EnvEmail } from './config/env-email';

interface EmailService {
  sendEmail(from: string, to: string, subject: string, body: string): void;
}

class NodemailerEmailService implements EmailService {
  private transporter: nodemailer.Transporter;

  constructor() {
    this.transporter = nodemailer.createTransport({
      service: EnvEmail.SMTP_HOST,
      auth: {
        user: EnvEmail.SMTP_USER,
        pass: EnvEmail.SMTP_PASS,
      },
    });
  }

  async sendEmail(
    from: string,
    to: string,
    subject: string,
    body: string
  ): Promise&amp;lt;void&amp;gt; {
    const mailOptions: nodemailer.SendMailOptions = {
      from,
      to,
      subject,
      text: body,
    };

    try {
      const info = await this.transporter.sendMail(mailOptions);
      console.log('Email sent:', info);
    } catch (error) {
      if (error instanceof Error) {
        console.error('Error sending email:', error.message);
        if (error.message.includes('Authentication')) {
          console.error(
            'Authentication error. Please check your SMTP credentials.'
          );
        } else {
          console.error('Non-critical error occurred. Retrying...');
        }
      } else {
        console.error('Unexpected error sending email:', error);
      }
      throw error;
    }
  }
}

class EmailSender {
  private emailService: EmailService;

  constructor(emailService: EmailService) {
    this.emailService = emailService;
  }

  sendEmail(from: string, to: string, subject: string, body: string): void {
    this.emailService.sendEmail(from, to, subject, body);
  }
}

const emailService = new NodemailerEmailService();
const emailSender = new EmailSender(emailService);

emailSender.sendEmail(
  EnvEmail.SMTP_USER,
  'williamkoller30@gmail.com',
  'Hello',
  'This is a test email'
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O Princípio da Inversão de Dependência (DIP) afirma que:&lt;br&gt;
Módulos de alto nível não devem depender de módulos de baixo nível. Ambos devem depender de abstrações.&lt;br&gt;
Abstrações não devem depender de detalhes. Detalhes devem depender de abstrações.&lt;br&gt;
Em termos simples, isso significa que as classes e módulos de alto nível (como lógica de negócios) devem depender de interfaces ou abstrações, e não de implementações concretas. As implementações concretas devem depender dessas abstrações, permitindo que as partes do sistema sejam mais flexíveis e menos acopladas.&lt;br&gt;
Como o código respeita o DIP&lt;br&gt;
Interface EmailService:&lt;br&gt;
Define um contrato para o serviço de envio de emails com o método sendEmail. Isso permite que qualquer classe que implemente essa interface possa ser usada para enviar emails, sem que a classe EmailSender precise saber os detalhes da implementação.&lt;/p&gt;

&lt;p&gt;Classe NodemailerEmailService:&lt;br&gt;
Implementa a interface EmailService e usa a biblioteca nodemailer para enviar emails.&lt;br&gt;
Contém detalhes específicos de como o email é enviado, como configuração do transporte e manipulação de erros, mas essas implementações não são conhecidas pela classe EmailSender.&lt;/p&gt;

&lt;p&gt;Classe EmailSender:&lt;br&gt;
Depende da abstração EmailService para enviar emails, não de uma implementação concreta. Isso permite que EmailSender use qualquer serviço que implemente EmailService sem modificar seu próprio código.&lt;br&gt;
O construtor de EmailSender recebe uma instância de EmailService, permitindo a injeção de dependências. Isso facilita a troca de implementações concretas (por exemplo, substituindo NodemailerEmailService por um outro serviço de email) sem alterar EmailSender.&lt;/p&gt;

&lt;p&gt;Justificativa de Conformidade com o DIP&lt;br&gt;
Dependência de Abstrações: EmailSender depende da abstração EmailService, não de NodemailerEmailService. Isso permite que a classe EmailSender permaneça desacoplada da implementação específica de envio de email.&lt;br&gt;
Flexibilidade e Manutenção: Como EmailSender usa a interface EmailService, podemos substituir NodemailerEmailService por qualquer outra implementação que também implemente EmailService, como um serviço de email baseado em API, sem precisar alterar a lógica de EmailSender.&lt;br&gt;
Injeção de Dependências: A injeção de uma implementação concreta de EmailService no construtor de EmailSender segue o princípio da injeção de dependências, que promove um acoplamento mais solto e uma maior flexibilidade no design do sistema.&lt;/p&gt;

&lt;p&gt;Exemplo de Extensão&lt;br&gt;
Para adicionar um novo serviço de email, como SendGridEmailService, que implementa EmailService, seria necessário apenas criar a nova classe:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class SendGridEmailService implements EmailService {
  async sendEmail(
    from: string,
    to: string,
    subject: string,
    body: string
  ): Promise&amp;lt;void&amp;gt; {
    // Implementação usando SendGrid API
    console.log(`Sending email via SendGrid from ${from} to ${to}: ${subject}`);
    // Código para enviar email usando SendGrid API
  }
}

const sendGridEmailService = new SendGridEmailService();
const emailSenderWithSendGrid = new EmailSender(sendGridEmailService);
emailSenderWithSendGrid.sendEmail(
  EnvEmail.SMTP_USER,
  'williamkoller30@gmail.com',
  'Hello',
  'This is a test email via SendGrid'
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neste exemplo, SendGridEmailService é uma nova implementação de EmailService, e EmailSender pode utilizá-la sem mudanças no seu código, exemplificando o Princípio da Inversão de Dependência (DIP).&lt;/p&gt;

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

&lt;p&gt;Adotar esses princípios pode transformar significativamente a maneira como você projeta e desenvolve software. Eles não são apenas recomendações teóricas, mas práticas comprovadas que ajudam a criar sistemas que são mais fáceis de entender, modificar e expandir. Ao investir tempo em entender e aplicar SOLID, você não apenas melhora a qualidade do seu código, mas também prepara sua base de código para um futuro mais sustentável e adaptável.&lt;/p&gt;

&lt;p&gt;Se você está buscando criar software que se destaca pela sua clareza e robustez, integrar os princípios SOLID em sua prática de desenvolvimento é um passo essencial. Com uma abordagem fundamentada nesses princípios, você estará bem posicionado para construir sistemas que não apenas atendem às necessidades atuais, mas que também se adaptam e evoluem com o tempo.&lt;/p&gt;

&lt;p&gt;Referências tiradas do livro Arquitetura Limpa por Robert C. Martin&lt;/p&gt;

&lt;p&gt;Repositorio no Github: &lt;a href="https://github.com/williamkoller/ts-node-solid-examples" rel="noopener noreferrer"&gt;https://github.com/williamkoller/ts-node-solid-examples&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Hoje iremos falar sobre a velocidade em percorrer um elemento em JavaScript</title>
      <dc:creator>William Koller</dc:creator>
      <pubDate>Tue, 05 Dec 2023 12:45:54 +0000</pubDate>
      <link>https://dev.to/williamkoller/hoje-iremos-falar-sobre-a-velocidade-em-percorrer-um-elemento-em-javascript-4me3</link>
      <guid>https://dev.to/williamkoller/hoje-iremos-falar-sobre-a-velocidade-em-percorrer-um-elemento-em-javascript-4me3</guid>
      <description>&lt;p&gt;Quando precisamos buscar uma lista de elementos em JavaScript sempre usamos .find(), mas o .find() usa o paradigma declarativo ou seja o paradigma declarativo em JavaScript se refere a uma abordagem de programação na qual você descreve o que deseja alcançar e deixa a linguagem cuidar da implementação dos detalhes.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const numbers = [10, 20, 30, 40, 50];

  function findGreaterThan30(element) {
    return element &amp;gt; 30;
  }

  const result = numbers.find(findGreaterThan30);

  console.log(result); // 40
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No paradigma imperativo em JavaScript, você fornece instruções detalhadas sobre como realizar uma tarefa. Nesse estilo de programação, você se concentra em especificar passo a passo como um programa deve executar as ações desejadas.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const numbers = [10, 20, 30, 40, 50];
  let result;

  function findGreaterThan30Imperative(array) {
    for (let i of Object.keys(array)) {
      if (array[i] &amp;gt; 30) {
        result = array[i];
        break;
      }
    }
  }

  findGreaterThan30Imperative(numbers);

  console.log(result); // 40
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ambos trazem o mesmo resultado, mas qual sera o mais rapido.&lt;/p&gt;

&lt;p&gt;Vamos passar para duas functions uma declarative() e a outra imperative()&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function declarative() {
  console.time('declarative');

  const numbers = [10, 20, 30, 40, 50];

  function findGreaterThan30(element) {
    return element &amp;gt; 30;
  }

  const result = numbers.find(findGreaterThan30);

  console.log(result); // 40

  console.timeEnd('declarative');
}

declarative();

function imperative() {
  console.time('imperative');

  const numbers = [10, 20, 30, 40, 50];
  let result;

  function findGreaterThan30Imperative(array) {
    for (let i of Object.keys(array)) {
      if (array[i] &amp;gt; 30) {
        result = array[i];
        break;
      }
    }
  }

  findGreaterThan30Imperative(numbers);

  console.log(result); // 40
  console.timeEnd('imperative');
}

imperative();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Executando e olhe a diferença:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5trkq6eskpofm6q91y6w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5trkq6eskpofm6q91y6w.png" alt="Image description" width="598" height="120"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Espero ter ajudado &amp;lt;3 e cuidado ao usar .find() em JavaScript.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>loop</category>
      <category>programming</category>
      <category>backenddevelopment</category>
    </item>
    <item>
      <title>Assinatura de commits</title>
      <dc:creator>William Koller</dc:creator>
      <pubDate>Fri, 17 Jun 2022 22:42:42 +0000</pubDate>
      <link>https://dev.to/williamkoller/assinatura-de-commits-2ac0</link>
      <guid>https://dev.to/williamkoller/assinatura-de-commits-2ac0</guid>
      <description>&lt;p&gt;Como conseguimos garantir que somos nós mesmos que fazemos os commits?!&lt;/p&gt;

&lt;p&gt;Qualquer pessoa pode alterar a configuração do git, colocar seu e-mail e dizer que foi você que subiu aquele commit.&lt;/p&gt;

&lt;p&gt;Para assinar commits, iremos ver o GNUPG.&lt;/p&gt;

&lt;p&gt;Nesse link: &lt;a href="https://www.gnupg.org/"&gt;gnupg&lt;/a&gt; vemos que GNUPG é The GNU Privacy Guard.&lt;/p&gt;

&lt;p&gt;É uma implementação completa e gratuita do padrão OpenPGP conforme definido pelo RFC4880 (também conhecido como PGP. O GnuPG permite criptografar e assinar dados e comunicações; possui um sistema de gerenciamento de chaves versátil, juntamente com módulos de acesso para todos os tipos de diretórios de chaves públicas. GnuPG, também conhecido como GPG, é uma ferramenta de linha de comando com recursos para facilitar a integração com outros aplicativos. O GnuPG também oferece suporte para S/MIME e Secure Shell (ssh).&lt;/p&gt;

&lt;p&gt;Instalação no linux&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt update 
sudo apt install gnupg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Iremos verificar se existe alguma chave criada no nosso computador.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gpg --list-secret-key --keyid-form LONG
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp9r4xdpy6lm6w6kmgjsc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp9r4xdpy6lm6w6kmgjsc.png" alt="Image description" width="456" height="123"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vamos criar a nossa chave&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gpg --full-generate-key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Selecionamos (1) para usarmos RSA&lt;/li&gt;
&lt;li&gt;4096 bits long&lt;/li&gt;
&lt;li&gt;y&lt;/li&gt;
&lt;li&gt;quanto tempo quer que seja valido a chave: 1y&lt;/li&gt;
&lt;li&gt;y&lt;/li&gt;
&lt;li&gt;Real name: seu nome
Email address: &lt;a href="mailto:seuemail@mail.com"&gt;seuemail@mail.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;selecionar O para salvar e sair.&lt;/li&gt;
&lt;li&gt;criar uma senha no seu computador para ter acesso a chave.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjpa7tivk4mz2hq21mel6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjpa7tivk4mz2hq21mel6.png" alt="Image description" width="400" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Iremos verificar a chave criada.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gpg --list-secret-key --keyid-form LONG
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Com esse retorno:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sec   rsa4096/1F64329A378F71EE 2022-06-17 [SC] [expires: 2023-06-17]
      8EF31698FB71ACAC945C4A3E1F64329A378F71EE
uid                 [ultimate] William Koller &amp;lt;williamkoller404@gmail.com&amp;gt;
ssb   rsa4096/43D2BB51F0668C4B 2022-06-17 [E] [expires: 2023-06-17]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Iremos copiar o sec =&amp;gt; &lt;code&gt;1F64329A378F71EE&lt;/code&gt; que é o id para pegarmos a chave publica e adicionar no github.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; gpg --armor --export 1F64329A378F71EE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pegamos a chave e adicionamos no github em GPG Keys&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftjbtgcp37arf58cqit7z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftjbtgcp37arf58cqit7z.png" alt="Image description" width="788" height="230"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agora iremos configurar o git para assinar commit e tags&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git config --global commit.gpgsign true
git config --global tag.gpgSign true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Criei esse projeto no github para exemplificar&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fix8aj4jxhe0hs0kzx8xb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fix8aj4jxhe0hs0kzx8xb.png" alt="Image description" width="800" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Precisamos adicionar a nossa chave no git&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git config --global user.signingkey 1F64329A378F71EE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quando formos commitar irá aparece essa tela para confirmamos a senha&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4a9vgyaktertug312wlg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4a9vgyaktertug312wlg.png" alt="Image description" width="387" height="409"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agora iremos verificar se o git esta vinculado ao nosso commit&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git log --show-signature -1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ww24b3l6b6sd2dc7trl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ww24b3l6b6sd2dc7trl.png" alt="Image description" width="800" height="162"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vamos no repositorio verificar se o usuário está verificado, clicamos hash do commit.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpiplfcwwqsz1g5gj65k7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpiplfcwwqsz1g5gj65k7.png" alt="Image description" width="800" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ultimo passo&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo nano ~/.gnupg/gpg.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E adicionar &lt;code&gt;use-agent&lt;/code&gt; e salvar e em seguida roda esse comando&lt;code&gt;gpgconf --launch gpg-agent&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Pronto agora temos a verificação de assinatura de commits.&lt;/p&gt;

&lt;p&gt;Espero ter ajudado.&lt;/p&gt;

</description>
      <category>git</category>
      <category>github</category>
      <category>gnupg</category>
      <category>linux</category>
    </item>
    <item>
      <title>Como criar um projeto com Nestjs do zero com deploy no Heroku usando Github Actions</title>
      <dc:creator>William Koller</dc:creator>
      <pubDate>Sat, 04 Jun 2022 16:29:42 +0000</pubDate>
      <link>https://dev.to/williamkoller/como-criar-um-projeto-com-nestjs-do-zero-com-deploy-no-heroku-usando-github-actions-517p</link>
      <guid>https://dev.to/williamkoller/como-criar-um-projeto-com-nestjs-do-zero-com-deploy-no-heroku-usando-github-actions-517p</guid>
      <description>&lt;p&gt;Ola devs e devas!&lt;/p&gt;

&lt;p&gt;Porque iremos usar Nestjs?!&lt;br&gt;
Nestjs é um framework Nodejs que conseguimos escalar muito rapidamente usando POO e é meu framework favorito.&lt;/p&gt;

&lt;p&gt;Em primeiro lugar precisa ter instalados &lt;code&gt;node&lt;/code&gt; e o cli do nestjs, para instalarmos o cli rodamos esse comando &lt;code&gt;npm i -g @nesjs/cli&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Agora iremos criar o projeto com cli do nest: &lt;code&gt;nest new api-example-dev.to-ci-cd&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;O cli do nest é muito poderoso e cria toda uma estrutura inicial para nós.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fao6ubi8o187ik395yv4z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fao6ubi8o187ik395yv4z.png" alt="Image description" width="774" height="605"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para acessar digitaremos: &lt;code&gt;cd api-example-dev.to-ci-cd &amp;amp;&amp;amp; code .&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Essa é a estrutura de pasta que temos:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftv0c4nz4c0ikir0d4ek7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftv0c4nz4c0ikir0d4ek7.png" alt="Image description" width="202" height="242"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agora iremos rodar o projeto com o comando: &lt;code&gt;yarn start:dev&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Aplicação de pé:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5bgmeg9ws6no0zb6zkvh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5bgmeg9ws6no0zb6zkvh.png" alt="Image description" width="800" height="135"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agora iremos criar o projeto no heroku:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk032m2erf6f8jo0uzsuo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk032m2erf6f8jo0uzsuo.png" alt="Image description" width="787" height="422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Antes disso, precisamos instalar o cli do heroku e fazer o login:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo snap install heroku --classic
heroku login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Iremos adicionar o remote do heroku no nosso projeto: &lt;code&gt;heroku git:remote -a api-example-dev-to-ci-cd&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiftrezfvjhiogn7bs9ra.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiftrezfvjhiogn7bs9ra.png" alt="Image description" width="800" height="103"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agora criaremos o arquivo Procfile que sera lido pelo heroku na hora que fizermos o push:&lt;/p&gt;

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

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

&lt;/div&gt;



&lt;p&gt;Agora iremos preparar para fazer o push:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git add .
git commit -m "chore: add setup"
git push heroku main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn6lajgzcmhjw6e5i0so0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn6lajgzcmhjw6e5i0so0.png" alt="Image description" width="764" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Iremos criar o nosso projeto no Github:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgvdsan5n5cjzyop4zxsa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgvdsan5n5cjzyop4zxsa.png" alt="Image description" width="754" height="909"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Precisamos adicionar a porta do projeto no heroku:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvf0240mwht9zv9z5g0hd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvf0240mwht9zv9z5g0hd.png" alt="Image description" width="800" height="474"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Iremos acessar a nossa aplicação:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3zds0y21ckq9syzd8sjj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3zds0y21ckq9syzd8sjj.png" alt="Image description" width="503" height="71"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tudo ok com nossa aplicação, agora iremos implementar nosso CI/CD para automatizar nossos deploy.&lt;/p&gt;

&lt;p&gt;Criaremos o arquivo &lt;code&gt;ci-cd.yml&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;name: 'CI/CD'

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  continuous-integration:
    runs-on: ubuntu-latest

    strategy:
      matrix:
        node-version: [16.x]

    steps:
      - uses: actions/checkout@v2

      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v1
        with:
          node-version: ${{ matrix.node-version }}

      - name: Install dependencies
        run: yarn install

  continuos-delivery:
    runs-on: ubuntu-latest

    needs: [continuous-integration]

    steps:
      - uses: actions/checkout@v2

      - name: Deploy to heroku
        if: ${{ github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main'}}
        uses: akhileshns/heroku-deploy@v3.12.12
        with:
          heroku_api_key: ${{ secrets.HEROKU_API_KEY }}
          heroku_app_name: ${{ secrets.HEROKU_APP_NAME }}
          heroku_email: ${{ secrets.HEROKU_EMAIL }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora iremos adicionar as secrets no Github:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkgohev2qkw83h69bhle7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkgohev2qkw83h69bhle7.png" alt="Image description" width="800" height="521"&gt;&lt;/a&gt;&lt;br&gt;
Iremos preparar para fazer o push, mas agora no github:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git add .
git commit -m "chore: add ci/cd workflow"
git push origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rodando o Actions:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fccbwlgppfwdv8q2l3xa6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fccbwlgppfwdv8q2l3xa6.png" alt="Image description" width="800" height="195"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agora iremos mudar o retorno para vermos o CI/CD funcionando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export class AppService {
  getHello(): { message: string } {
    return {
      message: `welcome to the @dev.to example api with CI/CD Heroku`,
    };
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Precisamos alterar o retorno na nossa controller também:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  getHello(): { message: string } {
    return this.appService.getHello();
  }
}

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

&lt;/div&gt;



&lt;p&gt;Preparando o push:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git add .
git commit -m "feat: add new return"
git push origen main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rodando a Action com a nova alteração:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcpw3mnj62oucnoxutqq0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcpw3mnj62oucnoxutqq0.png" alt="Image description" width="800" height="242"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Iremos acessar a aplicação novamente:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fid39ar487sn4ynum7caj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fid39ar487sn4ynum7caj.png" alt="Image description" width="720" height="196"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pronto, implementamos CI/CD no Github Actions com deploy no Heroku&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Rest e seus níveis de maturidade</title>
      <dc:creator>William Koller</dc:creator>
      <pubDate>Mon, 23 May 2022 19:36:22 +0000</pubDate>
      <link>https://dev.to/williamkoller/rest-e-seus-niveis-de-maturidade-3mf2</link>
      <guid>https://dev.to/williamkoller/rest-e-seus-niveis-de-maturidade-3mf2</guid>
      <description>&lt;p&gt;&lt;strong&gt;O que sabemos sobre Rest&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Muitos desenvolvedores "já sabem trabalhar com REST";&lt;/li&gt;
&lt;li&gt;Representational state of transfer (Transferência Representacional de Estado);&lt;/li&gt;
&lt;li&gt;surgiu em 2000 por Ray Fielding em uma dissertação de doutorado;&lt;/li&gt;
&lt;li&gt;Simplicidade;&lt;/li&gt;
&lt;li&gt;Stateless (sem guardar estado);&lt;/li&gt;
&lt;li&gt;Cacheável;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;REST: Níveis de maturidade (Richardson Maturity Model)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nível 0 - POX:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nível 0 de maturidade significa que uma determinada aplicação não utilizou os recursos de URI, métodos HTTP e Hypermedia (HATEOAS);&lt;/p&gt;

&lt;p&gt;Iremos notar que nesse exemplo modelo mais comum, faz uso apenas de verbos POST e GET:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;POST&lt;/strong&gt; - &lt;code&gt;http://localhost:3005/products/saveProduct&lt;/code&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd9osff8e48ah1ne5i8cm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd9osff8e48ah1ne5i8cm.png" alt="Image description" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GET&lt;/strong&gt; - &lt;code&gt;http://localhost:3005/products/getProduct/628bd53ff6a8e68c40859468&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqtyisnkbbt6zgx0tkl8s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqtyisnkbbt6zgx0tkl8s.png" alt="Image description" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Logo... &lt;em&gt;nada a ver com REST e muito distante de RESTful&lt;/em&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nível 1 - Recursos:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nível 1 de maturidade considera a utilização eficiente de URIs. Os recursos são mapeados, porém não empregam com eficiência o uso dos verbos.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fprhzzylab92gm2jggqbv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fprhzzylab92gm2jggqbv.png" alt="Image description" width="673" height="119"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nível 2 - VERBOS HTTP (HTTP VERBS):&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nível 2 de maturidade considera o uso eficiente de URIs e verbos HTTP.&lt;/p&gt;

&lt;p&gt;Nesse nível, a API suporta os seguintes verbos HTTP:&lt;/p&gt;

&lt;p&gt;– HTTP POST: utilizado para criar registro em banco de dados;&lt;/p&gt;

&lt;p&gt;– HTTP GET: utilizado para a leitura de registros em banco de dados;&lt;/p&gt;

&lt;p&gt;– HTTP PUT: utilizado para atualizar um determinado registro em banco de dados;&lt;/p&gt;

&lt;p&gt;– HTTP PATCH: utilizado para atualizar parte de um determinado registro em banco de dados.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST /products
{
 name: "Notebook Samsung Book Np550 Celeron"
 description: "4gb 500gb 15.6 W11 Cinza"
}
&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;HTTP/1.1 201 Created
Location: /products/628bda5a314e825e8965e05a
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Nível 3 - HATEOAS:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nível 3 conhecido por &lt;em&gt;Hypermedia as the Engine of Application State&lt;/em&gt;, Roy Fielding descreve HATEOAS como uma das premissas necessárias para considerar um API RESTful.&lt;/p&gt;

&lt;p&gt;Exemplo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftd1uovywfzxnpepmuvw8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftd1uovywfzxnpepmuvw8.png" alt="Image description" width="800" height="710"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Referências:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://mundoapi.com.br/destaques/alcancando-a-excelencia-do-rest-com-um-modelo-de-maturidade-eficiente/"&gt;Alcancando a excelencia do rest com um modelo de maturidade eficiente&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://blog.betrybe.com/desenvolvimento-web/api-rest-tudo-sobre/"&gt;Api rest tudo sobre&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Código de exemplo: &lt;a href="https://github.com/williamkoller/rest-example-with-nestjs"&gt;https://github.com/williamkoller/rest-example-with-nestjs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Espero ter ajudado &amp;lt;3;&lt;/p&gt;

</description>
      <category>rest</category>
      <category>developer</category>
      <category>backend</category>
      <category>api</category>
    </item>
    <item>
      <title>Como evitar SQL Injection no MongoDB</title>
      <dc:creator>William Koller</dc:creator>
      <pubDate>Tue, 26 Apr 2022 01:09:27 +0000</pubDate>
      <link>https://dev.to/williamkoller/como-evitar-sql-injection-no-mongodb-1fo3</link>
      <guid>https://dev.to/williamkoller/como-evitar-sql-injection-no-mongodb-1fo3</guid>
      <description>&lt;p&gt;&lt;strong&gt;O que é SQL Injection?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;SQL Injection é um ataque no qual código malicioso é passado para um servidor SQL, que o executa. O ataque pode resultar em acesso não autorizado a dados confidenciais, ou destruição de dados críticos.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Como saber se uma query não previne SQL Injection?!&lt;/p&gt;

&lt;p&gt;Neste exemplo estou usando CodeQL, o que é CodeQL?!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;É um mecanismo de análise de código que descobre vulnerabilidades.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nesse exemplo na aba de security do github:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fehs5k1nb7orvw8ius963.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fehs5k1nb7orvw8ius963.png" alt="Image description" width="800" height="572"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;O code sacanner nos avisa, que se uma consulta de banco de dados (como uma consulta SQL ou NoSQL) for criada a partir de dados fornecidos pelo usuário sem higienização suficiente, um usuário mal-intencionado poderá executar consultas de banco de dados mal-intencionadas.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Como recomendação para queries NoSQL, podemos usar um operador como &lt;code&gt;$eq&lt;/code&gt; do MongoDB&lt;/p&gt;

&lt;p&gt;Iremos fazer um refactor no UsersRepository para evitar SQL Injection:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn6v711myd0am4vpspv9m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn6v711myd0am4vpspv9m.png" alt="Image description" width="800" height="348"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Depois de rodar o Github Actions, notamos que não tem mais alerta na aba de security no github:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6s3vgbwux6gtgtzghzn0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6s3vgbwux6gtgtzghzn0.png" alt="Image description" width="800" height="518"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;E assim não temos mais alerta de SQL Injection;&lt;/p&gt;

&lt;p&gt;Repo de exemplo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/williamkoller/my-readings"&gt;https://github.com/williamkoller/my-readings&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Espero ter te ajudado de alguma maneira, pode comentar e compartilhar.&lt;/p&gt;

</description>
      <category>nestjs</category>
      <category>mongodb</category>
      <category>typescript</category>
      <category>codaql</category>
    </item>
    <item>
      <title>Como remover dados duplicados em go</title>
      <dc:creator>William Koller</dc:creator>
      <pubDate>Fri, 15 Apr 2022 02:03:42 +0000</pubDate>
      <link>https://dev.to/williamkoller/como-remover-dados-duplicados-em-go-4d0p</link>
      <guid>https://dev.to/williamkoller/como-remover-dados-duplicados-em-go-4d0p</guid>
      <description>&lt;p&gt;Ola devs e devas&lt;/p&gt;

&lt;p&gt;Iremos usar de exemplo um slice de int para passarmos dados duplicados nele.&lt;/p&gt;

&lt;p&gt;Criaremos um arquivo &lt;code&gt;main.go&lt;/code&gt; de exemplo&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqgf3i1e0r4c8hpqktm4d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqgf3i1e0r4c8hpqktm4d.png" alt="Image description" width="800" height="361"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Esse é o retorno:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;intSliceValues [1 2 3 3 4 4 5 6 7 8 9 9 9]&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Agora iremos criar uma function para remover os dados duplicados&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Futiwplynqh0ft2h2c1i1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Futiwplynqh0ft2h2c1i1.png" alt="Image description" width="800" height="609"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;E agora no main, ficaria assim:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frklklfm63fudlqnlyur1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frklklfm63fudlqnlyur1.png" alt="Image description" width="800" height="795"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O retorno:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;intSliceValues [1 2 3 3 4 4 5 6 7 8 9 9 9]&lt;br&gt;
uniqueSlice [1 2 3 4 5 6 7 8 9]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Conclusão:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A partir da função main, declaramos um slice. Também imprimimos o valor original da slice.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Definimos uma função onde estamos passando os valores originais do slice e verificando as duplicatas.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lógica para verificação de duplicatas: Para isso definimos outra slice e atribuindo os primeiros valores verificando se o valor já existe na novo slice ou não. Ele retorna o slice sem duplicatas.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Estamos chamando a função &lt;em&gt;removeDuplicate&lt;/em&gt; da função principal onde o slice de retorno da função é impressa.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Espeor ter ajudado.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Como trabalhar com Switch no Golang</title>
      <dc:creator>William Koller</dc:creator>
      <pubDate>Sat, 02 Apr 2022 21:51:12 +0000</pubDate>
      <link>https://dev.to/williamkoller/como-trabalhar-com-switch-no-golang-50ai</link>
      <guid>https://dev.to/williamkoller/como-trabalhar-com-switch-no-golang-50ai</guid>
      <description>&lt;p&gt;Ola devs e devas.&lt;/p&gt;

&lt;p&gt;Para ilustrar esses exemplos de &lt;code&gt;switch&lt;/code&gt; em golang, iremos usar como exemplo dia da semana.&lt;/p&gt;

&lt;p&gt;Esse primeiro exemplo iremos definir uma function para obtermos a resposta do dia da semana:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fypgde73dvon4j74ryqvv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fypgde73dvon4j74ryqvv.png" alt="Image description" width="800" height="1032"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nesse exemplo iremos usar o switch com o &lt;code&gt;fallthrough&lt;/code&gt;;&lt;br&gt;
O que seria a palavra-chave &lt;code&gt;fallthrough&lt;/code&gt; é usada na instrução &lt;code&gt;switch&lt;/code&gt; em golang. Esta palavra-chave é usada no bloco &lt;code&gt;switch&lt;/code&gt; case. Se a palavra-chave de fallthrough estiver presente no bloco case, ela transferirá o controle para o próximo caso, mesmo que o caso atual possa ter correspondência:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Farbe5qexro37gnauvjtv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Farbe5qexro37gnauvjtv.png" alt="Image description" width="800" height="1313"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nesse exemplo iremos definir uma variavel com inferencia de tipo &lt;code&gt;var dayWeek string&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft1l7t6kc1zabgl4q90yk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft1l7t6kc1zabgl4q90yk.png" alt="Image description" width="800" height="1044"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nesse exemplo podemos utilizar o &lt;code&gt;switch&lt;/code&gt; desta maneira:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3habjg0lfiiufnxf0s6w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3habjg0lfiiufnxf0s6w.png" alt="Image description" width="800" height="953"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para executarmos cada exemplo, ficaria assim:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fae2kc46qg7ufiylxyfn8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fae2kc46qg7ufiylxyfn8.png" alt="Image description" width="800" height="1128"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;E como respostas, ficaria assim:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;go run main.go&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr6rws0dpiwnx6vhbcewg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr6rws0dpiwnx6vhbcewg.png" alt="Image description" width="96" height="166"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Um ponto importante&lt;/strong&gt;, &lt;em&gt;no caso do golang nao precisamos usar o palavra-chave break apos o retorno do case. Pois o go ja faz isso automaticamente&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Notamos que podemos usar os 4 exemplos diferentes de &lt;code&gt;switch&lt;/code&gt; em go.&lt;/p&gt;

&lt;p&gt;Espero ter ajudado.&lt;/p&gt;

</description>
      <category>go</category>
      <category>linux</category>
      <category>switch</category>
      <category>developer</category>
    </item>
    <item>
      <title>Como trabalhar com Loop no Dart</title>
      <dc:creator>William Koller</dc:creator>
      <pubDate>Thu, 17 Feb 2022 18:17:09 +0000</pubDate>
      <link>https://dev.to/williamkoller/como-trabalhar-com-loop-no-dart-3780</link>
      <guid>https://dev.to/williamkoller/como-trabalhar-com-loop-no-dart-3780</guid>
      <description>&lt;p&gt;Iremos iniciar uma lista&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var list = [1, 2, 3, 4, 5, 6];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Utilizando o método &lt;code&gt;forEach&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;list.forEach((element) {
  print(element);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Utilizando &lt;code&gt;for&lt;/code&gt; Loop&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for (int i = 0; i &amp;lt; list.length; i++) {
  var e = list[i];
  print(e);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Utilizando &lt;code&gt;for in&lt;/code&gt; Loop&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for (var e in &amp;lt;List&amp;gt;[list]) {
  print(e);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Utilizando &lt;code&gt;while&lt;/code&gt; Loop&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var i = 0;
while (i &amp;lt; list.length) {
  print(list[i]);
  i++;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Code-0-4-1/loop-dart"&gt;loop-dart&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Primeiros passos em Dart, como instalar Dart SDK no Linux e compilar Hello World!!</title>
      <dc:creator>William Koller</dc:creator>
      <pubDate>Thu, 17 Feb 2022 12:13:12 +0000</pubDate>
      <link>https://dev.to/williamkoller/primeiros-passos-em-dart-como-instalar-dart-sdk-no-linux-e-compilar-hello-world-258g</link>
      <guid>https://dev.to/williamkoller/primeiros-passos-em-dart-como-instalar-dart-sdk-no-linux-e-compilar-hello-world-258g</guid>
      <description>&lt;p&gt;Como instalar Dart SDK no Linux&lt;/p&gt;

&lt;p&gt;Instalar usando &lt;code&gt;apt-get&lt;/code&gt;:&lt;/p&gt;

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

sudo apt-get update
sudo apt-get install apt-transport-https
sudo sh -c 'wget -qO- https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -'
sudo sh -c 'wget -qO- https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list &amp;gt; /etc/apt/sources.list.d/dart_stable.list'


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

&lt;/div&gt;

&lt;p&gt;Em seguida instalar Dart SDK:&lt;/p&gt;

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

sudo apt-get update
sudo apt-get install dart


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

&lt;/div&gt;

&lt;p&gt;Verificar a versão instalada:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;dart --version&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F30cp9dzaqodefhx2cus5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F30cp9dzaqodefhx2cus5.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como compilar Hello World em Dart:&lt;/p&gt;

&lt;p&gt;Criar arquivo com extensao &lt;code&gt;.dart&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch hello_world.dart&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Criando Hello World em Dart:&lt;/p&gt;

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

void main() {
  print("Hello, world");
}


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

&lt;/div&gt;

&lt;p&gt;Como compilar o arquivo &lt;code&gt;hello_world.dart&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;dart run hello_world.dart&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fiaz5mo8z08syndf9zep9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fiaz5mo8z08syndf9zep9.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Conclusão:&lt;/p&gt;

&lt;p&gt;Simples de compilar dart.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
