Fábrica de Código

Nesse artigo vou mostrar 4 maneiras de como eu uso ChatGPT no meu dia a dia. E no video abaixo você pode ver mais detalhes de como eu fiz tudo abaixo.

1 – Montar SQLs

Recentemente eu resolvi um bug para identificar e renomear valores duplicados. Vamos usar como exemplo a tabela abaixo

IdNumero
10001
20001
30001

Note que a coluna Numero tem valores duplicados

Meu SQL tem que pegar o valor dessa coluna e concatenar com algum index para ficar assim “0001_1”, “0001_2” e assim sucessivamente. O valor da primeira linha não deve ser alterado e deve continuar “0001”

Para resolver fiz o seguinte prompt no ChatGPT

Crie um script sql para alterar valores duplicados em uma coluna de uma tabela. A tabela vai se chamar Pedido e as colunas são Id do tipo int, Numero do tipo varchar(15). Esse script deve conter begin tran

Esse foi o resultado

BEGIN TRANSACTION;

-- Atualizar valores duplicados na coluna Numero
WITH NumerosDuplicados AS (
    SELECT 
        Id,
        Numero,
        ROW_NUMBER() OVER(PARTITION BY Numero ORDER BY Id) AS RowNum
    FROM 
        Pedido
)
UPDATE Pedido
SET Numero = CONCAT(Numero, '_', Id)
FROM Pedido AS p
INNER JOIN NumerosDuplicados AS d
ON p.Id = d.Id
WHERE d.RowNum > 1;

COMMIT;

Você também pode argumentar informando que algo está errado, como por exemplo

o update não está respeitando o RowNum

E esse foi o resultado

BEGIN TRANSACTION;

-- Seleciona e altera valores duplicados na coluna Numero
WITH NumerosDuplicados AS (
    SELECT 
        Id,
        Numero,
        ROW_NUMBER() OVER(PARTITION BY Numero ORDER BY Id) AS RowNum
    FROM 
        Pedido
)
UPDATE Pedido
SET Numero = CONCAT(NumerosDuplicados.Numero, '_', NumerosDuplicados.RowNum)
FROM Pedido
INNER JOIN NumerosDuplicados
ON Pedido.Id = NumerosDuplicados.Id
WHERE NumerosDuplicados.RowNum > 1;

COMMIT;

2 – Criação de teste unitário

Vamos usar como exemplo a classe abaixo

import { z } from "zod";
import { User } from "@/application/authetication/entities/User";
import { type UserRepository } from "@/application/authetication/repositories/UserRepository";
import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime";
import { Toast } from "@/infra/Notification";

export const CreateUserSchema = z.object({
    email: z.string().email(),
    password: z.string(),
});

export type CreateUserInput = z.infer<typeof CreateUserSchema>;

export class CreateUserHandler {
    constructor(readonly userRepo: UserRepository, readonly router: AppRouterInstance, readonly toast: Toast) {}

    async execute(input: CreateUserInput): Promise<User | null> {
        try {
            const user = await this.userRepo.create(new User("", input.email, false), input.password);
            if (!user) {
                throw new Error("Ocorreu um erro ao tentar criar sua conta. Atualize a página e tente novamente.");
            }

            this.toast.showSuccess("Conta criada com sucesso.");
            this.router.push("/login");
            this.router.refresh();

            return user;
        } catch (error) {
            this.toast.showError((error as Error).message);
            return null;
        }
    }
}

E fiz o seguinte prompt

Dado a classe abaixo, crie testes unitários utilizando vitest
import { z } from "zod";
import { User } from "@/application/authetication/entities/User";
import { type UserRepository } from "@/application/authetication/repositories/UserRepository";
import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime";
import { Toast } from "@/infra/Notification";

export const CreateUserSchema = z.object({
    email: z.string().email(),
    password: z.string(),
});

export type CreateUserInput = z.infer<typeof CreateUserSchema>;

export class CreateUserHandler {
    constructor(readonly userRepo: UserRepository, readonly router: AppRouterInstance, readonly toast: Toast) {}

    async execute(input: CreateUserInput): Promise<User | null> {
        try {
            const user = await this.userRepo.create(new User("", input.email, false), input.password);
            if (!user) {
                throw new Error("Ocorreu um erro ao tentar criar sua conta. Atualize a página e tente novamente.");
            }

            this.toast.showSuccess("Conta criada com sucesso.");
            this.router.push("/login");
            this.router.refresh();

            return user;
        } catch (error) {
            this.toast.showError((error as Error).message);
            return null;
        }
    }
}

E esse foi o resultado

import { describe, it, expect, vi, beforeEach } from "vitest";
import { User } from "@/application/authetication/entities/User";
import { CreateUserHandler, CreateUserInput } from "@/application/authetication/handlers/CreateUserHandler";
import { type UserRepository } from "@/application/authetication/repositories/UserRepository";
import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime";
import { Toast } from "@/infra/Notification";

describe("CreateUserHandler", () => {
    let userRepo: UserRepository;
    let router: AppRouterInstance;
    let toast: Toast;
    let handler: CreateUserHandler;

    beforeEach(() => {
        // Mock das dependências
        userRepo = {
            create: vi.fn()
        } as unknown as UserRepository;

        router = {
            push: vi.fn(),
            refresh: vi.fn()
        } as unknown as AppRouterInstance;

        toast = {
            showSuccess: vi.fn(),
            showError: vi.fn()
        } as unknown as Toast;

        handler = new CreateUserHandler(userRepo, router, toast);
    });

    it("deve criar o usuário e redirecionar para a página de login em caso de sucesso", async () => {
        const input: CreateUserInput = { email: "test@example.com", password: "password123" };
        const newUser = new User("1", input.email, false);

        (userRepo.create as vi.Mock).mockResolvedValue(newUser);

        const result = await handler.execute(input);

        expect(userRepo.create).toHaveBeenCalledWith(newUser, input.password);
        expect(toast.showSuccess).toHaveBeenCalledWith("Conta criada com sucesso.");
        expect(router.push).toHaveBeenCalledWith("/login");
        expect(router.refresh).toHaveBeenCalled();
        expect(result).toBe(newUser);
    });

    it("deve mostrar um erro e retornar null se o repositório retornar null", async () => {
        const input: CreateUserInput = { email: "test@example.com", password: "password123" };
        (userRepo.create as vi.Mock).mockResolvedValue(null);

        const result = await handler.execute(input);

        expect(toast.showError).toHaveBeenCalledWith("Ocorreu um erro ao tentar criar sua conta. Atualize a página e tente novamente.");
        expect(result).toBeNull();
    });

    it("deve mostrar uma mensagem de erro e retornar null se ocorrer um erro", async () => {
        const input: CreateUserInput = { email: "test@example.com", password: "password123" };
        const errorMessage = "Erro de criação";
        
        (userRepo.create as vi.Mock).mockRejectedValue(new Error(errorMessage));

        const result = await handler.execute(input);

        expect(toast.showError).toHaveBeenCalledWith(errorMessage);
        expect(result).toBeNull();
    });
});

Obviamente pode ser que precise de algum ajuste conforme eu fiz no vídeo acima, mas o resultado já me atendeu completamente e me fez economizar o tempo de escrever todos esses testes e criar todos os mocks.

3 – Transformar uma classe para um JSON

Vez ou outra quando estamos criando algum endpoint em alguma api, criamos uma classe para ser o input desse request. E aí precisamos de gerar um json para colocar no body do request com base nessa classe. É aí que o ChatGPT entra.

Vamos pegar como exemplo a classe abaixo escrita em C#

public class Pessoa
{
	public long Id { get; set; }
	public string FirstName { get; set; }
	public string LastName { get; set; }
}

Eu fiz esse prompt para gerar o JSON

Transforme essa classe em c# em um json
public class Pessoa
{
	public long Id { get; set; }
	public string FirstName { get; set; }
	public string LastName { get; set; }
}

E esse foi o resultado

{
  "Id": 123456,
  "FirstName": "João",
  "LastName": "Silva"
}

Lembrando que no C# o formato que usamos é o camelCase para esses casos, eu fiz outro prompt para alterar esse formato

Altere o json para o formato camel case

E esse foi o resultado

{
  "id": 123456,
  "firstName": "João",
  "lastName": "Silva"
}

E o melhor é que ele ainda popula com dados fictícios para facilitar o teste.

4 – Gerar dados fictícios

Recentemente desenvolvi uma nova feature para importação de dados em um sistema, e gerar um um arquivo csv varios registros para teste não é uma tarefa fácil.

Para resolver isso fiz o seguinte prompt para o ChatGPT

gerar aquivo csv com 100 registros com os campos nome, cpf e data de nascimento

Conforme você pode ver no vídeo acima, ele gerou o csv com todos os dados que eu precisava para o meu teste e ainda mostrou em um código como ele fez para gerar.

Isso é fantástico.

Conclusão

Essas inteligencias artificiais podem ser de grande valia para o nosso dia a dia, mas você ainda precisa saber pensar. Se você não sabe escrever o que você quer, elas vão te responder qualquer coisa.

Sem contar que você pode economizar um bom tempo no seu dia a dia.

E você, como está usando o ChatGPT no seu dia a dia?