Alura > Cursos de Inteligência Artificial > Cursos de Engenharia de LLMs & Agentes > Conteúdos de Engenharia de LLMs & Agentes > Primeiras aulas do curso Desenvolvimento Back-end com IA: Fundamentos Práticos

Desenvolvimento Back-end com IA: Fundamentos Práticos

Desenvolvimento Back-end com Assistência de IA - Introdução

Apresentando o curso e o instrutor

Olá a todas as pessoas, bem-vindas ao curso de Desenvolvimento Back-end com assistência de IA da Alura.

Meu nome é Thiago Gonzaga. Sou pessoa desenvolvedora há 20 anos. Já trabalhei com diversas linguagens. Minha linguagem principal é Java, mas também trabalhei com Python, C#, PHP e Go.

Explicando objetivos e abrangência do curso

Viemos compartilhar nossa experiência trabalhando com desenvolvimento focado em IA nos últimos anos: como nós e nosso time aplicamos IA no dia a dia, boas práticas e fluxos de trabalho relevantes ao desenvolver com IA. Também vamos abordar as principais formas de utilizar IA para apoiar o cotidiano, para extrair o máximo valor e qualidade, que é o mais importante.

Embora este curso se concentre em uma tecnologia específica, ele serve para qualquer linguagem. O que vamos trabalhar aqui — os fluxos, as especificações e os padrões que vamos utilizar — é aplicável a qualquer linguagem. Você poderá usar em PHP, Java, Python e C#, sem problema.

Indicando recursos no GitHub e finalizando a introdução

Nossos repositórios no GitHub estarão disponíveis em todas essas linguagens. Todos os recursos que vamos utilizar durante o processo de desenvolvimento, os prompts (instruções) que preparamos durante o processo, também estarão disponíveis no GitHub, organizados por aula e por linguagem, com os prompts (instruções) detalhados que utilizamos em cada etapa, para cada aula que veremos ao longo do curso.

Esperamos que aproveitem.

Desenvolvimento Back-end com Assistência de IA - Por que base sólida importa mais com IA

Apresentando o curso e contextualizando a ia

Olá a todas as pessoas. Neste curso, nós vamos aprender a desenvolver uma API para o Meetup usando Spring Boot e Java, com assistência de IA. Antes de começarmos, é importante esclarecer alguns pontos sobre essa tecnologia.

Provavelmente vimos no X, no Instagram e no próprio LinkedIn diversas pessoas afirmando que já não precisamos de pessoas programadoras, pois qualquer pessoa pode gerar uma aplicação. Em certo sentido, isso parece verdade, porque a IA passa uma sensação de poder. Porém, se refletirmos, qualquer pessoa também pode cozinhar: basta comprar um livro de receitas e seguir os passos em casa. A grande questão é se o resultado sairá bom ou não.

Ressaltando a importância da base de programação

Também percebemos que, junto com a multidão de pessoas fazendo coisas com IA sem conhecimentos técnicos, estão ocorrendo incidentes, como problemas de segurança e vazamentos de dados. Afirmamos que a base de programação é extremamente importante. Se você é uma pessoa desenvolvedora que está começando agora, recomendamos iniciar pelos vídeos de introdução à carreira de back-end (camada de serviço).

Por que essa base é tão importante? Porque é ela que fornecerá o conhecimento necessário para avaliar se o que a IA gerou é bom ou não, e se está correto ou não. Para quem não tem esse conhecimento, o simples fato de o sistema funcionar pode parecer suficiente: “funciona, faz o que eu quero, está ótimo”. No entanto, essa pessoa não sabe o que acontece por trás; os dados podem estar sendo expostos e diversos problemas podem surgir: desempenho, escalabilidade e outros que ocorrem quando não sabemos lidar corretamente com a tecnologia.

Explicando o funcionamento da ia generativa e a necessidade de detalhamento

Quando falamos de IA aqui, referimo-nos à IA generativa. No nosso caso, falamos de LLM, ou Large Language Models (Modelos de Linguagem de Grande Porte), isto é, modelos de linguagem projetados especificamente para gerar texto. Como código é texto, também podemos gerar código conversando com a IA. O ponto é que esse tipo de modelo é estatístico: as respostas são baseadas em cálculos de probabilidade, retornando o que tem maior chance de ser o que foi solicitado. Isso não significa que esteja correto; significa apenas que é o mais provável de acordo com o pedido, não necessariamente o certo. Por isso, a IA nem sempre fornecerá informações corretas.

Também é importante reforçar que a IA não é feita para estudar no sentido de substituir fontes de conteúdo. Não devemos usar a IA para extrair conteúdo de estudo. O ideal é utilizar livros, cursos e métodos mais consolidados para aprender, e usar a IA como apoio para fundamentar e acelerar o dia a dia. Em muitos aspectos, a IA agiliza tarefas como criar resumos, ajudar a planejar e detalhar informações. Contudo, se não soubermos exatamente o que queremos, a IA também não saberá como ajudar. O que tende a acontecer? Provavelmente surgirão alucinações: informações incorretas, muitas vezes sem relação com o que foi solicitado.

Pensemos no caso mais simples possível: o Waze. Suponha que queremos ir para São Joaquim. São Joaquim pode ser uma cidade, um bairro, o nome de uma avenida ou de uma rua. Se buscarmos apenas “São Joaquim”, o aplicativo retornará várias opções. O que fazemos, então? Começamos a detalhar: se é uma rua ou uma avenida, o número, a cidade, o bairro, até que o Waze nos leve ao destino correto. Com a IA, não é diferente. Se pedirmos algo muito amplo, ela devolverá alguma coisa, porque foi projetada para sempre responder de alguma forma. Correto ou não, haverá uma resposta. A IA dificilmente dirá que não sabe; por isso, é fundamental termos em mente a importância de detalhar com precisão o que queremos quando trabalhamos com IA.

Escolhendo a ferramenta de desenvolvimento e comparando limites de uso

Para este curso, nós vamos utilizar o Cursor. Optamos pelo Cursor não por fidelidade à marca, mas porque atualmente oferece a melhor relação custo-benefício. Existem outras opções, como Codex, Claude Code e o próprio GitHub Copilot. A maioria oferece um plano de assinatura mensal de 20 dólares e segue um padrão semelhante: ao atingir o limite de uso, o acesso é interrompido. Geralmente há um limite a cada 5 horas e também um limite semanal; ao esgotá-lo, é preciso esperar o reinício desse período para continuar o trabalho.

No Cursor, a dinâmica é diferente: há um limite por modelo. Nós podemos escolher com qual modelo trabalhar e temos um limite atribuído para cada um. Quando atingimos esse limite, ainda é possível continuar trabalhando usando o Modo Alto, em que o próprio Cursor escolherá o modelo para a tarefa. Nesse caso, não teremos controle sobre qual modelo será usado, mas, pelo menos, não ficaremos bloqueados aguardando o reinício do limite de acesso. Essa é uma das razões pelas quais escolhemos o Cursor para este curso.

Preparando o ambiente com wsl e docker

Outra coisa também muito importante para este curso...

Se usamos Windows, é recomendável ter o WSL (Subsistema do Windows para Linux). O Linux apresenta sutilezas interessantes para quem trabalha com desenvolvimento. Portanto, se usamos Windows, é bom trabalhar com WSL. WSL e Docker são ferramentas que serão muito importantes para nós durante todo este curso.

Iniciando com um prompt básico e observando o comportamento do modelo

Vamos começar com um prompt (instrução) básico. Imaginemos que estamos começando a programar. Definimos um prompt simples: criar uma entidade JPA em Java para representar um evento com ID, título, descrição, data, hora, limite de vagas e uso de boas práticas. Gostamos de usar, no desenvolvimento, o modelo Sonnet, da Anthropic, porque apresenta boa relação custo-benefício e entrega qualidade. Mas não faria muita diferença usar o modo Auto; se preferirmos usar Auto o tempo todo, não haverá problema.

Ao executar esse prompt, o que acontece? O sistema solicitará a resposta ao modelo, analisará as informações e perceberá que não há nada além do pedido: nosso projeto está em branco, sem contexto adicional. O modelo não pode adivinhar o que queremos, então se baseará especificamente no que foi solicitado nesse prompt simples e gerará o código.

Apresentando a primeira entidade gerada com lombok

Para ilustrar esse primeiro resultado, veja a entidade gerada com uso de Lombok. Note que ela segue boas práticas de JPA, inclui validações e mapeia a tabela “eventos”; entretanto, faz uso de anotações do Lombok para gerar métodos automaticamente:

package br.com.alura.meetupapi.model;

import jakarta.persistence.*;
import jakarta.validation.constraints.*;
import lombok.*;

import java.time.LocalDateTime;

@Entity
@Table(name = "eventos")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@EqualsAndHashCode(of = "id")
@ToString(exclude = "descricao")
public class Evento {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotBlank(message = "O título é obrigatório")
    @Size(max = 150, message = "O título deve ter no máximo 150 caracteres")
    @Column(nullable = false, length = 150)
    private String titulo;

    @Size(max = 1000, message = "A descrição deve ter no máximo 1000 caracteres")
    @Column(length = 1000)
    private String descricao;

    @NotNull(message = "A data e hora são obrigatórias")
    @Future(message = "A data e hora do evento devem ser no futuro")
    @Column(name = "data_hora", nullable = false)
    private LocalDateTime dataHora;

    @NotBlank(message = "O local é obrigatório")
    @Size(max = 255, message = "O local deve ter no máximo 255 caracteres")
    @Column(nullable = false)
    private String local;

    @NotNull(message = "O limite de vagas é obrigatório")
    @Min(value = 1, message = "O limite de vagas deve ser de pelo menos 1")
    @Max(value = 10000, message = "O limite de vagas não pode exceder 10000")
    @Column(name = "limite_vagas", nullable = false)
    private Integer limiteVagas;

}

Observe como o modelo decidiu usar Lombok por conta própria. É exatamente aqui que entra nosso papel de orientar a IA conforme nossas preferências de projeto.

Ajustando preferências e removendo o lombok

Ao abrir o resultado gerado, observamos algo importante: o modelo tomou algumas decisões por nós que não preferimos adotar durante o desenvolvimento. Por exemplo, não gostamos de usar Lombok. Entendemos que Lombok pode levar ao que chamamos de Dependency Hell (inferno de dependências), pois adiciona muita dependência e, na prática, realiza muito processamento de classes dentro da JVM, algo invisível e fora do nosso controle. Além disso, costuma gerar um grande número de anotações. Preferimos uma abordagem mais simples.

Esse é um ponto relevante: precisamos mencionar explicitamente o que queremos. Podemos dizer no prompt que não queremos usar Lombok. O modelo então removerá as anotações do Lombok e transformará o código de acordo com a preferência, adicionando os métodos necessários, como getters (acessadores) e setters (mutadores). Preferimos assim.

Para deixar claro o ajuste feito na conversa com a IA, a instrução enviada foi algo como: “não quero usar lombok”.

A seguir está a versão sem Lombok, com os métodos gerados explicitamente e mantendo as mesmas validações e mapeamentos JPA:

Exibindo a entidade sem lombok e avaliando o resultado

package br.com.alura.meetupapi.model;

import jakarta.persistence.*;
import jakarta.validation.constraints.*;
import java.time.LocalDateTime;
import java.util.Objects;

@Entity
@Table(name = "eventos")
public class Evento {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotBlank(message = "O título é obrigatório")
    @Size(max = 150, message = "O título deve ter no máximo 150 caracteres")
    @Column(nullable = false, length = 150)
    private String titulo;

    @Size(max = 1000, message = "A descrição deve ter no máximo 1000 caracteres")
    @Column(length = 1000)
    private String descricao;

    @NotNull(message = "A data e hora são obrigatórias")
    @Future(message = "A data e hora do evento devem ser no futuro")
    @Column(name = "data_hora", nullable = false)
    private LocalDateTime dataHora;

    @NotBlank(message = "O local é obrigatório")
    @Size(max = 255, message = "O local deve ter no máximo 255 caracteres")
    @Column(nullable = false)
    private String local;

    @NotNull(message = "O limite de vagas é obrigatório")
    @Min(value = 1, message = "O limite de vagas deve ser de pelo menos 1")
    @Max(value = 10000, message = "O limite de vagas não pode exceder 10000")
    @Column(name = "limite_vagas", nullable = false)
    private Integer limiteVagas;

    public Evento() {
    }

    public Evento(String titulo, String descricao, LocalDateTime dataHora, String local, Integer limiteVagas) {
        this.titulo = titulo;
        this.descricao = descricao;
        this.dataHora = dataHora;
        this.local = local;
        this.limiteVagas = limiteVagas;
    }

    public Long getId() {
        return id;
    }

    public String getTitulo() {
        return titulo;
    }

    public void setTitulo(String titulo) {
        this.titulo = titulo;
    }

    public String getDescricao() {
        return descricao;
    }

    public void setDescricao(String descricao) {
        this.descricao = descricao;
    }

    public LocalDateTime getDataHora() {
        return dataHora;
    }

    public void setDataHora(LocalDateTime dataHora) {
        this.dataHora = dataHora;
    }

    public String getLocal() {
        return local;
    }

    public void setLocal(String local) {
        this.local = local;
    }

    public Integer getLimiteVagas() {
        return limiteVagas;
    }

    public void setLimiteVagas(Integer limiteVagas) {
        this.limiteVagas = limiteVagas;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Evento evento = (Evento) o;
        return Objects.equals(id, evento.id);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }

    @Override
    public String toString() {
        return "Evento{" +
                "id=" + id +
                ", titulo='" + titulo + '\'' +
                ", dataHora=" + dataHora +
                ", local='" + local + '\'' +
                ", limiteVagas=" + limiteVagas +
                '}';
    }
}

Esse ajuste mostra bem como a IA nos ajuda no boilerplate: deixamos claro que não queremos Lombok e a ferramenta gera os getters/setters, além de manter equals, hashCode e toString — tudo alinhado às boas práticas. Você pode aceitar, revisar e lapidar conforme os padrões da sua equipe.

Aproveitando a ia para boilerplate e reconhecendo suas limitações

A IA é muito eficiente em lidar com a parte mais mecânica do desenvolvimento, o chamado boilerplate (código repetitivo). Gerar getters e setters manualmente consome tempo e é desnecessário. Algumas IDEs (ambientes de desenvolvimento integrado), como o IntelliJ, já ofereciam essa funcionalidade antes do advento da IA, evitando que digitássemos tudo na mão. Com a IA, isso fica ainda mais fácil. Em resumo, a IA é excelente para gerar boilerplate, esqueleto de código e padrões repetitivos bem conhecidos e amplamente difundidos no GitHub ou no Stack Overflow. Essas informações compõem parte do treinamento da IA, o que facilita sua geração.

Onde a IA não vai bem? Ao exigir decisões de arquitetura muito complexas ou regras de negócio muito específicas. Muitas empresas possuem regras proprietárias protegidas por segredo industrial. Esse tipo de informação não está disponível para treinamento, pois pertence às empresas. Logo, o modelo não sabe e, consequentemente, não oferecerá uma resposta adequada. É essencial ter isso em mente ao escolher o que desejamos gerar com a IA.

Considerando a data de corte dos modelos e selecionando versões estáveis

Outro ponto relevante: ao trabalhar com um modelo de linguagem, ele não tem conhecimento infinito nem treinamento em tempo real. Todo modelo possui uma data de corte, a chamada cutoff date (data de corte). O conhecimento do modelo vai até essa data. Por exemplo, no caso do Sonnet, da Anthropic, a data de corte foi maio de 2025. Ele conhece bem o que ocorreu até maio de 2025; novidades posteriores não fazem parte do seu conhecimento. Por isso, para este projeto, não podemos escolher trabalhar com a versão mais recente do Java ou com a versão mais recente do Spring Boot lançadas depois da data de corte, porque o modelo não as conhece bem.

Pode haver alguma tentativa de inferência? Sim. O modelo pode ter visto conteúdo em preview (prévia) disponível publicamente, mas uma prévia não é o resultado final. Muita coisa pode mudar entre a versão preliminar e a versão de disponibilidade geral — General Availability (GA) (disponibilidade geral). Por exemplo, o Java 25 foi lançado em setembro de 2025, bem depois da data de corte. O Spring Boot 4 foi lançado em novembro do mesmo ano, também fora desse escopo.

Ao escolher tecnologias, é muito importante conhecer a data de corte para ajustar a arquitetura. Além disso, estar sempre no estado de bleeding edge (vanguarda) — isto é, usar continuamente versões mais recentes ou em lançamento — raramente é uma boa ideia. É melhor permitir que as versões sejam bem testadas e validadas antes de adotá-las. Portanto, recomendamos trabalhar com versões de suporte de longo prazo — Long Term Support (LTS) (suporte de longo prazo), como Java 21 e Spring Boot 3, que já são consolidadas e amplamente testadas. Essa é uma decisão de linguagem e de arquitetura mais coerente.

Desenvolvimento Back-end com Assistência de IA - Preparando o ambiente

Apresentando os Dev Containers e suas vantagens

Antes de começarmos, vamos preparar nosso ambiente para desenvolver. Preferimos trabalhar com Dev Containers (contêineres de desenvolvimento), que são uma extensão do Visual Studio Code (VS Code). Hoje, praticamente todas as IDEs (Ambientes de Desenvolvimento Integrado), como Windsurf, Cursor e AntiGravity, são baseadas no VS Code, então as extensões do VS Code funcionam normalmente.

Com essa extensão, definimos como será o ambiente e executamos essa definição dentro de um contêiner. Assim, evitamos o problema do “na minha máquina funciona”. Conseguimos criar um ambiente reproduzível, que se comporta sempre da mesma maneira, e evitamos instalar dependências diretamente na máquina, o que gera arquivos desnecessários, cache e diversas configurações que acabam se misturando com outras aplicações. O Dev Container isola tudo isso, mantém as dependências externas fora do sistema operacional principal e concentra o necessário em um ambiente isolado.

Outra vantagem é o processo de onboarding (integração de novas pessoas) em equipes maiores. Basta disponibilizarmos o Dev Container para que a pessoa já possa iniciar sem instalar dependências externas, ficando pronta para desenvolver. Além disso, se trocarmos de laptop e precisarmos configurar tudo novamente, a definição do Dev Container recria o ambiente para nós, e já podemos começar a programar.

Definindo os requisitos do Dev Container

Nós já preparamos um pacote pronto para facilitar. O que estamos solicitando para esse Dev Container é:

O interessante é que temos acesso a todo o Marketplace (loja de extensões) do VS Code, então podemos definir no Dev Container quais extensões serão instaladas para aquele ambiente específico. Isso permite manter o conjunto de extensões do IDE o mais enxuto possível globalmente, ativando apenas o necessário por projeto.

Também vamos configurar o port forwarding (encaminhamento de portas): a API (interface de programação de aplicações) na porta 8080 e o MySQL na porta 3306, lembrando que ambos ficarão disponíveis via localhost (máquina local), para facilitar o acesso durante o desenvolvimento.

Por fim, adicionamos um postCreateCommand para executar a resolução de dependências do Maven (dependency:resolve) ao criar o ambiente, otimizando o processo de baixar as dependências necessárias com antecedência.

Definindo variáveis de ambiente e separando serviços com Docker Compose

Vamos trabalhar com variáveis de ambiente simples. Não devemos fazer isso em produção nem expor a senha root em produção; trata-se apenas de um ambiente de desenvolvimento.

Para isso, vamos usar um Docker Compose (ferramenta de orquestração do Docker). Teremos uma imagem com Java executando o comando sleep infinity, ou seja, uma imagem na qual poderemos executar comandos dentro do contêiner. Precisaremos executar Maven e Git, então utilizaremos uma imagem com Java e outra com MySQL, que será onde ficará o banco de dados. É recomendável manter ambos isolados.

Ao final, recomendamos manter separados o Dev Container (contêiner de desenvolvimento) e o Docker Compose. Evitaremos gerar um Dev Container com o Docker Compose dentro, pois preferimos que fiquem separados. Isso facilita o trabalho, especialmente na hora de fazer modificações e controle de versão. Às vezes será necessário alterar alguma versão das dependências no Docker Compose, e, mantendo-os separados, não será preciso modificar o Dev Container se tudo estiver funcionando corretamente.

Gerando a configuração inicial do Dev Container

Vamos executar. Nosso projeto está totalmente em branco; não há nada, é uma pasta vazia. Não há nenhum contexto, então a ferramenta verificará se a configuração existe; caso não exista, criará tudo para nós.

Foi criada a pasta ".devcontainer" e o arquivo devcontainer.json já com a definição: Java com Spring Boot, Docker Compose, Maven, Java 21, as extensões desejadas, as portas e o comando de pós-criação.

Abaixo está o devcontainer.json gerado com esses requisitos, incluindo as features (Java 21 com Maven, Git e GitHub CLI), as extensões de VS Code, o encaminhamento das portas 8080 e 3306, as variáveis de ambiente para o MySQL e o postCreateCommand para resolver as dependências do Maven:

{
    "name": "Java 21 + Spring Boot 3.4",
    "dockerComposeFile": "docker-compose.yml",
    "service": "app",
    "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
    "features": {
        "ghcr.io/devcontainers/features/java:1": {
            "version": "21",
            "installMaven": true
        },
        "ghcr.io/devcontainers/features/git:1": {},
        "ghcr.io/devcontainers/features/github-cli:1": {}
    },
    "customizations": {
        "vscode": {
            "extensions": [
                "vmware.vscode-spring-boot",
                "pivotal.vscode-boot-dev-pack",
                "vscjava.vscode-java-pack"
            ]
        }
    },
    "forwardPorts": [8080, 3306],
    "portsAttributes": {
        "8080": {
            "label": "Spring Boot API",
            "onAutoForward": "notify"
        },
        "3306": {
            "label": "MySQL",
            "onAutoForward": "silent"
        }
    },
    "remoteEnv": {
        "MYSQL_ROOT_PASSWORD": "root",
        "MYSQL_DATABASE": "meetup_db"
    },
    "postCreateCommand": "mvn dependency:resolve"
}

Ajustando o workspace do Dev Container

Vamos fazer um ajuste: não deixamos um determinado item nessa configuração, pois geralmente causa problemas, sobretudo ao usar WSL. Preferimos manter apenas o caminho /workspaces. O gerador sempre cria isso.

Para aplicar esse ajuste, alteramos a propriedade workspaceFolder para apontar somente para /workspaces:

"workspaceFolder": "/workspaces",

Revisando e corrigindo o Docker Compose

No Docker Compose, é necessário corrigir algo no final. Foi gerado um Docker Compose com os serviços devcontainer21 e sleepinfinity. O caminho do workspace (espaço de trabalho) já foi definido como /workspaces. Porém, ocorreu um erro; por isso é importante revisar o que foi gerado. Na prática, era apenas um ponto fora do lugar.

Aqui está o docker-compose.yml com os serviços app (execução do Java com sleep infinity) e mysql (MySQL 8.0), incluindo variáveis de ambiente, volume nomeado para persistência e healthcheck. Note que o serviço app depende do MySQL estar saudável:

services:
  app:
    image: mcr.microsoft.com/devcontainers/java:21
    command: sleep infinity
    volumes:
      - ../:/workspaces:cached
    depends_on:
      mysql:
        condition: service_healthy
    networks:
      - devcontainer-net

  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: meetup_db
    volumes:
      - mysql-data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-uroot", "-p${MYSQL_ROOT_PASSWORD}"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s
    networks:
      - devcontainer-net
networks:
  devcontainer-net:
    driver: bridge

Corrigindo o mapeamento de volumes

No final, ajustamos o mapeamento de volume para apontar corretamente para a raiz do workspace. O erro era literalmente um ponto fora do lugar no caminho. A correção ficou assim:

volumes:
      - ../..:/workspaces:cached

Reabrindo o projeto no container e inicializando o ambiente

Vamos salvar as alterações feitas manualmente. Em seguida, vamos acionar Ctrl+Shift+P e escolher a opção "Dev Containers: Reopen in Container". Se a opção não aparecer, basta pesquisar que ela surge.

Agora vamos carregar no Dev Container. As dependências serão instaladas. Verifiquemos se o terminal (terminal) já está disponível. O download já foi concluído e o ambiente foi criado; já estamos dentro do contêiner.

Validando as ferramentas instaladas no contêiner

No terminal, o prompt indica o workspace do VS Code. Vamos verificar o mvn com mvn version. Também podemos executar gh version para conferir a CLI do GitHub e verificar o git. Tudo está instalado, com o ambiente pronto para começar o desenvolvimento.

Para validar rapidamente as ferramentas dentro do contêiner, execute:

mvn --version

Em seguida, confira a CLI do GitHub:

gh version

E por fim, verifique o Git:

git --version

Sobre o curso Desenvolvimento Back-end com IA: Fundamentos Práticos

O curso Desenvolvimento Back-end com IA: Fundamentos Práticos possui 206 minutos de vídeos, em um total de 58 atividades. Gostou? Conheça nossos outros cursos de Engenharia de LLMs & Agentes em Inteligência Artificial, ou leia nossos artigos de Inteligência Artificial.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda Engenharia de LLMs & Agentes acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas