← Voltar IA

IA e Programação

Professor Ronaldo Lavestein
Módulo 5 · IA e Programação

Você herdou um programa que funciona. Agora precisa fazê-lo evoluir sem perder o controle.

O laboratório de informática da escola empresta notebooks, kits Arduino e câmeras para aulas e projetos. Um aluno começou um pequeno programa em Python para registrar os empréstimos, mas deixou o curso antes de terminar. O código funciona para um caso simples — e agora ficou com você.

Durante este módulo, o mesmo projeto receberá novos pedidos, apresentará erros, precisará guardar dados, ganhará testes e será preparado para outra pessoa continuar. A IA participará de todas essas etapas, mas com uma regra: ela ajuda a investigar e modificar; você continua responsável por compreender, decidir e comprovar.

Regra central

Se você não consegue explicar o que mudou, por que mudou e como comprovou que funciona, a tarefa ainda não terminou — mesmo que o código tenha sido escrito pela IA.

Antes de começar — este módulo não ensina Python do zero

Você não precisa ser especialista, mas precisa reconhecer o básico para que a IA não vire um atalho que esconda aquilo que você ainda não aprendeu.

Se isso ainda estiver novo demais

Volte primeiro para Programação de Computadores. Aqui vamos aprender a trabalhar com IA durante o desenvolvimento, não substituir os fundamentos da linguagem.

Como seguir esta aula sem se perder

A partir daqui, cada etapa diz explicitamente o que você deve fazer. Não avance no automático.

LEIA

É explicação ou contexto. Não altere nem execute nada a menos que a própria caixa mande.

FAÇA AGORA

É uma ação sua: editar arquivo, executar programa, criar pasta, testar ou anotar resultado.

PROMPT PARA A IA

Copie o texto da caixa e envie à IA junto com o contexto pedido. Depois confira a resposta; não a aceite automaticamente.

PARE E CONFIRA

Não siga enquanto você não conseguir verificar o resultado indicado.

1. Segunda-feira — o projeto chega às suas mãos

O professor entrega um arquivo chamado app.py. Antes de pedir “melhore esse código”, você precisa descobrir o que já existe e o que realmente funciona.

equipamentos = {
    "NB01": {"nome": "Notebook 01", "disponivel": True},
    "CAM01": {"nome": "Câmera 01", "disponivel": True},
    "ARD01": {"nome": "Kit Arduino 01", "disponivel": True}
}


def emprestar(codigo):
    codigo = codigo.strip().upper()
    item = equipamentos.get(codigo)

    if item is None:
        return "Equipamento não encontrado."

    if not item["disponivel"]:
        return "Equipamento indisponível."

    item["disponivel"] = False
    return f'{item["nome"]} emprestado com sucesso.'


codigo = input("Código do equipamento: ")
print(emprestar(codigo))

FAÇA AGORA — confirme o ponto de partida

  1. Crie ou abra app.py com exatamente o código acima.
  2. Execute com NB01.
  3. Execute novamente com nb01.
  4. Execute novamente com XX99.
  5. Anote as três mensagens exibidas.

Não altere o código ainda.

PARE E CONFIRA

NB01 e nb01 devem ser reconhecidos como o mesmo código; XX99 deve ser recusado como inexistente. Se isso não aconteceu, corrija primeiro a digitação do programa inicial.

2. Antes de modificar, faça a IA ajudá-lo a ler o que já existe

Você poderia perguntar “esse código está bom?”. Isso convida uma avaliação genérica. O objetivo agora é construir um mapa do comportamento.

PROMPT PARA A IA — copie e envie agora

Ainda não altere o código. Explique este programa para alguém que conhece variáveis, if e funções, mas está aprendendo dicionários. Responda em quatro partes: 1. quais dados o programa guarda; 2. o que a função emprestar recebe; 3. quais decisões ela toma; 4. o que muda nos dados quando um empréstimo é aceito. Depois proponha três entradas para eu prever o resultado antes de executar.

FAÇA AGORA — confira a explicação no código

Volte ao app.py e localize onde aparecem: o dicionário equipamentos, o parâmetro codigo, as duas decisões com if e a alteração de disponivel para False.

PARE E CONFIRA

Se você não consegue apontar no código a evidência de uma afirmação da IA, ainda não trate essa afirmação como entendimento.

3. Terça-feira — chega o primeiro pedido real de mudança

O responsável pelo laboratório testa o protótipo e identifica duas limitações: o programa precisa registrar para quem o equipamento foi emprestado e também precisa permitir a devolução.

LEIA — este é o impulso que queremos evitar

Adicione nome do aluno, devolução, menu e deixe tudo profissional.

Esse pedido mistura requisitos, não define casos problemáticos e dá liberdade demais para reconstruir o projeto.

PROMPT PARA A IA — transforme o pedido em regras

Não escreva código ainda. Para o programa atual, precisamos: - registrar o nome de quem recebe um equipamento; - impedir novo empréstimo enquanto ele estiver indisponível; - permitir devolução; - após devolver, o equipamento deve voltar a ficar disponível e deixar de ter responsável. Liste as alterações necessárias nos dados e nas funções. Depois proponha casos de teste. Preserve a estrutura atual sempre que possível.

FAÇA AGORA

Leia a resposta da IA e verifique se ela manteve o programa atual como base. Neste ponto, não aceite código ainda. O resultado desta etapa é apenas uma lista de mudanças e casos de teste.

4. Antes do novo código, registre o comportamento esperado

LEIA — não execute nada nesta etapa

A tabela abaixo ainda não é um teste automatizado e não é para ser “rodada”. Ela funciona como um contrato: registra o que deverá acontecer depois da mudança.

SituaçãoResultado esperadoO que comprova?
Emprestar NB01 para AnaEmpréstimo aceito; NB01 fica indisponível e ligado a Ana.Caminho principal.
Emprestar NB01 novamenteOperação recusada.Não permite dois empréstimos simultâneos.
Devolver NB01NB01 volta a ficar disponível e sem responsável.Regra de devolução completa.
Usar código XX99Equipamento não encontrado.Entrada inexistente.
Digitar “ nb01 ”Código é normalizado e reconhecido.Entrada equivalente.

FAÇA AGORA — responda antes de seguir

Sem executar o programa, responda para si mesmo: (1) o que deve acontecer se NB01 já estiver emprestado? (2) depois de uma devolução, quais dois dados precisam mudar?

PARE E CONFIRA

Você deve conseguir responder: o segundo empréstimo é recusado; na devolução, disponivel volta a True e o responsável deixa de existir.

5. Faça a primeira alteração pequena — em partes

Agora você vai modificar o programa pela primeira vez. Não substitua tudo por um programa novo. Vamos alterar a versão existente em etapas curtas.

FAÇA AGORA — Parte A: amplie os dados

Substitua somente o dicionário equipamentos pelo bloco abaixo. O novo campo registra quem está com cada item; None significa que não há responsável.

equipamentos = {
    "NB01": {
        "nome": "Notebook 01",
        "disponivel": True,
        "emprestado_para": None
    },
    "CAM01": {
        "nome": "Câmera 01",
        "disponivel": True,
        "emprestado_para": None
    },
    "ARD01": {
        "nome": "Kit Arduino 01",
        "disponivel": True,
        "emprestado_para": None
    }
}

PARE E CONFIRA

Cada equipamento deve ter agora exatamente três informações: nome, disponivel e emprestado_para.

FAÇA AGORA — Parte B: troque a função de empréstimo e acrescente a devolução

Substitua a função emprestar() antiga pelo bloco abaixo e coloque devolver() logo depois. Copie exatamente como está, mesmo que você desconfie de alguma coisa. Ainda existe um comportamento que vamos investigar.

def emprestar(codigo, aluno):
    codigo = codigo.strip().upper()
    item = equipamentos.get(codigo)

    if item is None:
        return "Equipamento não encontrado."
    if not item["disponivel"]:
        return "Equipamento indisponível."

    item["disponivel"] = False
    item["emprestado_para"] = aluno
    return f'{item["nome"]} emprestado para {aluno}.'


def devolver(codigo):
    codigo = codigo.strip().upper()
    item = equipamentos.get(codigo)

    if item is None:
        return "Equipamento não encontrado."
    if item["disponivel"]:
        return "Este equipamento já está disponível."

    item["emprestado_para"] = None
    return f'{item["nome"]} devolvido com sucesso.'

FAÇA AGORA — Parte C: atualize a chamada da função

A função emprestar() agora precisa de dois valores. Substitua somente as linhas finais do programa por:

codigo = input("Código do equipamento: ")
aluno = input("Nome do aluno: ")
print(emprestar(codigo, aluno))

FAÇA AGORA — primeiro teste da nova versão

Salve e execute uma vez. Digite NB01 e depois Ana. Você deve receber uma mensagem dizendo que Notebook 01 foi emprestado para Ana.

Agora faremos um teste temporário

As três linhas de interação acima não estão erradas. Vamos apenas retirá-las por alguns minutos para testar várias operações na mesma execução.

FAÇA AGORA — substitua temporariamente as três linhas finais por estas

print(emprestar("NB01", "Ana"))
print(emprestar("NB01", "Bruno"))
print(devolver("NB01"))
print(emprestar("NB01", "Bruno"))

Execute uma única vez.

PARE E OBSERVE — não corrija ainda

O primeiro empréstimo é aceito e o segundo é recusado, como esperado. Depois a função informa que a devolução aconteceu, mas o novo empréstimo para Bruno continua sendo recusado. Não há erro de sintaxe; há um estado incoerente. Esse defeito é proposital nesta etapa.

6. Quarta-feira — investigue o bug antes de corrigir

Agora existe uma evidência concreta: depois de devolver, o equipamento continua indisponível. Em vez de pedir “arruma”, vamos localizar exatamente onde a regra deixa de ser verdadeira.

PROMPT PARA A IA — investigue sem corrigir

Não corrija ainda. Simule esta sequência usando o código atual: 1. emprestar("NB01", "Ana"); 2. emprestar("NB01", "Bruno"); 3. devolver("NB01"); 4. emprestar("NB01", "Bruno"). Depois de cada etapa, mostre os valores de disponivel e emprestado_para de NB01. Identifique em qual etapa o estado deixa de representar a regra esperada.

FAÇA AGORA — confirme no programa, não apenas na resposta da IA

Troque temporariamente as quatro chamadas finais pelo bloco abaixo. Ele mostra o estado real de NB01 depois de cada operação.

print(emprestar("NB01", "Ana"))
print(equipamentos["NB01"])

print(emprestar("NB01", "Bruno"))
print(equipamentos["NB01"])

print(devolver("NB01"))
print(equipamentos["NB01"])

print(emprestar("NB01", "Bruno"))
print(equipamentos["NB01"])

PARE E LOCALIZE

O segundo empréstimo é corretamente recusado. O problema aparece depois de devolver("NB01"): emprestado_para volta a None, mas disponivel continua False. É nessa etapa que o estado deixa de representar a regra esperada.

PROMPT PARA A IA — agora sim peça a menor correção

Agora proponha a menor correção possível. Não altere nomes, estrutura ou mensagens fora do necessário. Depois diga quais testes da tabela anterior precisam ser repetidos.

FAÇA AGORA — aplique somente a correção necessária

Dentro de devolver(), antes de limpar o responsável, acrescente:

item["disponivel"] = True

Repita o teste completo. O segundo empréstimo deve continuar recusado enquanto NB01 está emprestado, e Bruno deve conseguir recebê-lo depois da devolução.

Checkpoint 1 — versão aprovada em memória

Depois de comprovar a correção, remova os print temporários de investigação e deixe seu app.py assim:

equipamentos = {
    "NB01": {
        "nome": "Notebook 01",
        "disponivel": True,
        "emprestado_para": None
    },
    "CAM01": {
        "nome": "Câmera 01",
        "disponivel": True,
        "emprestado_para": None
    },
    "ARD01": {
        "nome": "Kit Arduino 01",
        "disponivel": True,
        "emprestado_para": None
    }
}


def emprestar(codigo, aluno):
    codigo = codigo.strip().upper()
    item = equipamentos.get(codigo)

    if item is None:
        return "Equipamento não encontrado."
    if not item["disponivel"]:
        return "Equipamento indisponível."

    item["disponivel"] = False
    item["emprestado_para"] = aluno
    return f'{item["nome"]} emprestado para {aluno}.'


def devolver(codigo):
    codigo = codigo.strip().upper()
    item = equipamentos.get(codigo)

    if item is None:
        return "Equipamento não encontrado."
    if item["disponivel"]:
        return "Este equipamento já está disponível."

    item["disponivel"] = True
    item["emprestado_para"] = None
    return f'{item["nome"]} devolvido com sucesso.'


acao = input("Digite E para emprestar ou D para devolver: ").strip().upper()
codigo = input("Código do equipamento: ")

if acao == "E":
    aluno = input("Nome do aluno: ")
    print(emprestar(codigo, aluno))
elif acao == "D":
    print(devolver(codigo))
else:
    print("Opção inválida.")

PARE E CONFIRA

No teste temporário você comprovou empréstimo, bloqueio de segundo empréstimo, devolução e novo empréstimo. Agora vamos descobrir um problema diferente: o programa esquece tudo quando termina.

7. Quinta-feira — o programa funciona, mas esquece tudo quando fecha

FAÇA AGORA — reproduza o problema

  1. Com o Checkpoint 1, execute o programa e empreste NB01 para Ana.
  2. O programa termina.
  3. Execute novamente e tente emprestar NB01 para Bruno.

O segundo empréstimo será aceito porque o dicionário é recriado toda vez que o programa começa.

Agora existe uma necessidade concreta: o estado precisa sobreviver ao encerramento. A equipe decide usar dados/equipamentos.json.

PROMPT PARA A IA — planeje antes de escrever código

O programa atual guarda equipamentos em um dicionário e perde as alterações ao encerrar. Quero persistir esse estado em dados/equipamentos.json usando apenas a biblioteca padrão do Python. Antes de escrever código, proponha: 1. quando os dados devem ser carregados; 2. quando devem ser salvos; 3. o que deve acontecer na primeira execução, quando o arquivo ainda não existe; 4. quais erros não devemos esconder silenciosamente.

PARE E CONFIRA

A resposta precisa distinguir primeira execução de arquivo existente com problema. “Se der qualquer erro, começar do zero” esconderia defeitos reais.

8. Reproduza a primeira falha de persistência

Antes de alterar a versão aprovada, vamos reproduzir o problema de abertura do arquivo em um arquivo temporário.

FAÇA AGORA — crie teste_json.py

Na mesma pasta do projeto, crie um arquivo chamado teste_json.py com:

import json

ARQUIVO_DADOS = "dados/equipamentos.json"


def carregar_dados():
    with open(ARQUIVO_DADOS, "r", encoding="utf-8") as arquivo:
        return json.load(arquivo)


equipamentos = carregar_dados()
print(equipamentos)

FAÇA AGORA

Garanta que a pasta dados e o arquivo equipamentos.json ainda não existam e execute teste_json.py.

FileNotFoundError: [Errno 2] No such file or directory:
'dados/equipamentos.json'

PROMPT PARA A IA — explique antes de corrigir

Na primeira execução do projeto, carregar_dados() gera FileNotFoundError para dados/equipamentos.json. O comportamento desejado é: se ainda não houver arquivo, iniciar com os equipamentos padrão; se existir, carregar os dados salvos. Explique a causa antes de propor a menor alteração.

PARE E CONFIRA

O erro não significa que “JSON não funciona”. Significa apenas que o programa tentou abrir para leitura um arquivo que ainda não existe.

9. Verifique a API antes de confiar em um nome convincente

LEIA — exemplo proposital de sugestão errada da IA

Imagine que a IA sugira Path.makedirs() para criar a pasta. Não coloque isso no projeto. O nome parece plausível, mas esse método não existe em pathlib.Path.

PROMPT PARA A IA — exija verificabilidade

Você sugeriu Path.makedirs(). Antes de alterar meu código, indique a classe e o método exatos que está assumindo, os parâmetros relevantes e o que devo confirmar na documentação oficial do Python. Se o método sugerido não existir, corrija a orientação sem inventar outro.

Para este caso, o método correto é Path.mkdir(). Antes de salvar, podemos criar a pasta com ARQUIVO_DADOS.parent.mkdir(parents=True, exist_ok=True).

FAÇA AGORA — aplique a persistência em quatro partes

  1. No app.py, importe json e Path.
  2. Transforme os dados iniciais em uma função criar_dados_iniciais().
  3. Crie carregar_dados() e salvar_dados().
  4. Carregue no início e salve depois de uma ação de empréstimo ou devolução.

Depois compare sua versão com o checkpoint completo abaixo.

Checkpoint 2 — persistência funcionando

import json
from pathlib import Path

ARQUIVO_DADOS = Path("dados/equipamentos.json")


def criar_dados_iniciais():
    return {
        "NB01": {
            "nome": "Notebook 01",
            "disponivel": True,
            "emprestado_para": None
        },
        "CAM01": {
            "nome": "Câmera 01",
            "disponivel": True,
            "emprestado_para": None
        },
        "ARD01": {
            "nome": "Kit Arduino 01",
            "disponivel": True,
            "emprestado_para": None
        }
    }


def carregar_dados():
    if not ARQUIVO_DADOS.exists():
        return criar_dados_iniciais()

    with ARQUIVO_DADOS.open("r", encoding="utf-8") as arquivo:
        return json.load(arquivo)


def salvar_dados(dados):
    ARQUIVO_DADOS.parent.mkdir(parents=True, exist_ok=True)

    with ARQUIVO_DADOS.open("w", encoding="utf-8") as arquivo:
        json.dump(dados, arquivo, ensure_ascii=False, indent=2)


equipamentos = carregar_dados()


def emprestar(codigo, aluno):
    codigo = codigo.strip().upper()
    item = equipamentos.get(codigo)

    if item is None:
        return "Equipamento não encontrado."
    if not item["disponivel"]:
        return "Equipamento indisponível."

    item["disponivel"] = False
    item["emprestado_para"] = aluno
    return f'{item["nome"]} emprestado para {aluno}.'


def devolver(codigo):
    codigo = codigo.strip().upper()
    item = equipamentos.get(codigo)

    if item is None:
        return "Equipamento não encontrado."
    if item["disponivel"]:
        return "Este equipamento já está disponível."

    item["disponivel"] = True
    item["emprestado_para"] = None
    return f'{item["nome"]} devolvido com sucesso.'


acao = input("Digite E para emprestar ou D para devolver: ").strip().upper()
codigo = input("Código do equipamento: ")

if acao == "E":
    aluno = input("Nome do aluno: ")
    resultado = emprestar(codigo, aluno)
elif acao == "D":
    resultado = devolver(codigo)
else:
    resultado = "Opção inválida."

if acao in ("E", "D"):
    salvar_dados(equipamentos)

print(resultado)

FAÇA AGORA — teste de continuidade

  1. Apague o teste_json.py; ele não faz parte da versão final.
  2. Execute app.py e empreste NB01 para Ana.
  3. Encerre o programa.
  4. Execute novamente e tente emprestar NB01 para Bruno.

Agora o segundo empréstimo deve ser recusado. O arquivo JSON deve ter sido criado automaticamente.

PARE E CONFIRA

Se o JSON existir mas estiver corrompido, o erro ainda deve aparecer para ser investigado. Nesta etapa tratamos a ausência esperada do arquivo, não “qualquer erro de arquivo”.

10. Segunda semana — separe o necessário para poder testar

O app.py agora lê teclado, altera dados, salva arquivo e contém regras de negócio. Se outro arquivo importar app.py para testar uma função, os input() também serão executados. A separação agora tem motivo.

PROMPT PARA A IA — planeje a divisão mínima

Revise a estrutura atual sem reescrever tudo. Quero separar apenas o necessário para que as regras de empréstimo e devolução possam ser testadas sem executar input(). Identifique responsabilidades misturadas e proponha uma divisão mínima de arquivos. Preserve o comportamento já aprovado.

A estrutura aprovada para continuar será:

projeto_emprestimos/
├── app.py
├── emprestimos.py
├── dados/
│   └── equipamentos.json
└── test_emprestimos.py

FAÇA AGORA — crie emprestimos.py

Crie o arquivo e coloque nele somente os dados iniciais e as regras abaixo. Note a mudança importante: as funções recebem explicitamente o dicionário dados, em vez de depender de uma variável global.

def criar_dados_iniciais():
    return {
        "NB01": {
            "nome": "Notebook 01",
            "disponivel": True,
            "emprestado_para": None
        },
        "CAM01": {
            "nome": "Câmera 01",
            "disponivel": True,
            "emprestado_para": None
        },
        "ARD01": {
            "nome": "Kit Arduino 01",
            "disponivel": True,
            "emprestado_para": None
        }
    }


def emprestar(dados, codigo, aluno):
    codigo = codigo.strip().upper()
    item = dados.get(codigo)

    if item is None:
        return "Equipamento não encontrado."
    if not item["disponivel"]:
        return "Equipamento indisponível."

    item["disponivel"] = False
    item["emprestado_para"] = aluno
    return f'{item["nome"]} emprestado para {aluno}.'


def devolver(dados, codigo):
    codigo = codigo.strip().upper()
    item = dados.get(codigo)

    if item is None:
        return "Equipamento não encontrado."
    if item["disponivel"]:
        return "Este equipamento já está disponível."

    item["disponivel"] = True
    item["emprestado_para"] = None
    return f'{item["nome"]} devolvido com sucesso.'

Por enquanto, preserve o app.py

Nesta etapa você está apenas criando o núcleo testável. Não remova ainda as funções do app.py. Depois que o primeiro teste automatizado estiver funcionando, o Checkpoint 3 mostrará exatamente como adaptar o arquivo principal sem deixar o projeto quebrado no meio do caminho.

PARE E CONFIRA

emprestimos.py não deve conter input(), print() da interface nem leitura/escrita do JSON. Ele contém apenas criação dos dados iniciais e regras de empréstimo/devolução.

11. Transforme os testes escritos em testes automatizados

Agora cada teste pode criar seus próprios dados sem depender do que outro teste fez antes. Para automatizar as verificações, vamos usar pytest, que é uma dependência externa.

FAÇA AGORA — Parte A: crie o ambiente virtual

python -m venv .venv

Ative somente com o comando correspondente ao seu terminal:

# Windows PowerShell
.\.venv\Scripts\Activate.ps1

# Windows Prompt de Comando (cmd)
.venv\Scripts\activate.bat

# Linux/macOS
source .venv/bin/activate

FAÇA AGORA — Parte B: instale o pytest no ambiente ativado

python -m pip install pytest

FAÇA AGORA — Parte C: crie o primeiro teste

Crie test_emprestimos.py com:

from emprestimos import criar_dados_iniciais, emprestar, devolver


def test_devolver_libera_equipamento():
    dados = criar_dados_iniciais()

    emprestar(dados, "NB01", "Ana")
    devolver(dados, "NB01")

    assert dados["NB01"]["disponivel"] is True
    assert dados["NB01"]["emprestado_para"] is None

FAÇA AGORA — Parte D: execute

python -m pytest -q

PARE E CONFIRA

O primeiro teste precisa passar antes de você criar os demais. Se falhar, investigue a falha; não altere o teste apenas para deixá-lo verde.

PROMPT PARA A IA — amplie a proteção sem inventar regras

Com base nas regras já aprovadas do projeto, proponha testes para: empréstimo válido, segundo empréstimo recusado, devolução, código inexistente e normalização do código. Para cada teste, explique qual regra ele protege. Não crie regras novas.

FAÇA AGORA

Revise os testes propostos e copie para o mesmo test_emprestimos.py somente as funções de teste que correspondem à tabela de requisitos. Execute novamente python -m pytest -q.

Checkpoint 3 — projeto preparado para testes

Seu emprestimos.py já é o mostrado na etapa anterior. Agora substitua o conteúdo do app.py pela versão abaixo, que deixa a interface e a persistência no arquivo principal e importa as regras do núcleo:

import json
from pathlib import Path

from emprestimos import criar_dados_iniciais, emprestar, devolver

ARQUIVO_DADOS = Path("dados/equipamentos.json")


def carregar_dados():
    if not ARQUIVO_DADOS.exists():
        return criar_dados_iniciais()

    with ARQUIVO_DADOS.open("r", encoding="utf-8") as arquivo:
        return json.load(arquivo)


def salvar_dados(dados):
    ARQUIVO_DADOS.parent.mkdir(parents=True, exist_ok=True)

    with ARQUIVO_DADOS.open("w", encoding="utf-8") as arquivo:
        json.dump(dados, arquivo, ensure_ascii=False, indent=2)


dados = carregar_dados()
acao = input("Digite E para emprestar ou D para devolver: ").strip().upper()
codigo = input("Código do equipamento: ")

if acao == "E":
    aluno = input("Nome do aluno: ")
    resultado = emprestar(dados, codigo, aluno)
elif acao == "D":
    resultado = devolver(dados, codigo)
else:
    resultado = "Opção inválida."

if acao in ("E", "D"):
    salvar_dados(dados)

print(resultado)

PARE E CONFIRA

Neste ponto: emprestimos.py contém regras; app.py contém interface e persistência; test_emprestimos.py protege comportamentos já aprovados. Execute os testes mais uma vez antes de seguir.

12. “Na minha máquina funciona” — ambiente também faz parte do projeto

LEIA — situação simulada

Você não precisa trocar de computador para continuar a aula. Imagine que um colega copie a pasta e, ao executar os testes, receba:

ModuleNotFoundError: No module named 'pytest'

A regra de empréstimo não ficou errada. O novo ambiente ainda não possui a dependência usada para executar os testes.

PROMPT PARA A IA — diagnostique o ambiente

Os testes rodam em outro computador, mas neste laboratório Python 3.12 informa ModuleNotFoundError: No module named 'pytest'. Antes de mandar instalar qualquer coisa, explique o que preciso verificar sobre interpretador selecionado, ambiente virtual, instalação do pacote e registro de dependências do projeto.

FAÇA AGORA — registre a dependência

Como você criou um ambiente virtual controlado para este projeto, gere o arquivo:

python -m pip freeze > requirements.txt

PARE E CONFIRA

Abra requirements.txt e confirme que o pytest e suas dependências aparecem. O objetivo é tornar o ambiente reproduzível, não apenas “funcionar na sua máquina”.

13. O projeto agora contém dados de pessoas — nem todo contexto deve ir para a IA

LEIA — nenhuma alteração de código nesta etapa

Os testes da turma começam a usar nomes reais e alguém pensa em enviar o equipamentos.json inteiro para pedir ajuda. A IA não precisa de identidades reais para compreender a regra.

Evite

"emprestado_para": "Nome completo do aluno real"

Prefira

"emprestado_para": "ALUNO_TESTE_01"

PARE E CONFIRA

Antes de anexar um arquivo a uma IA, pergunte: “ela realmente precisa destes dados para resolver este problema?”

14. Revise o projeto antes de outra pessoa continuar

FAÇA AGORA — prepare somente o contexto necessário

Use o estado do Checkpoint 3. Envie à IA emprestimos.py, app.py e test_emprestimos.py. Não envie o JSON real se ele contiver nomes.

PROMPT PARA A IA — revisar sem editar

Revise este projeto sem editar ainda. Organize os achados em: - CORREÇÃO: comportamento que pode estar errado; - LEGIBILIDADE: algo que dificulta entender; - DUPLICAÇÃO: lógica repetida que aumenta risco de inconsistência; - TRATAMENTO DE ERROS: falhas que hoje não têm resposta adequada; - TESTABILIDADE: pontos difíceis de isolar ou testar. Para cada achado, cite o arquivo e o trecho. Não proponha mudanças apenas cosméticas.

FAÇA AGORA

Escolha uma única melhoria que tenha justificativa concreta. Faça uma alteração pequena e execute novamente todos os testes existentes.

PARE E CONFIRA

Se um comportamento mudou sem intenção, não foi apenas refatoração. Reverta ou investigue antes de continuar.

15. Uma IA com acesso ao repositório pode agir — e por isso exige mais controle

Até aqui você poderia copiar trechos para um chatbot. Agora imagine um agente conectado ao projeto, capaz de localizar arquivos, editá-los e executar testes.

LEIA — dois termos

Branch é uma linha separada de trabalho: permite experimentar uma mudança sem alterar diretamente a versão principal.

Diff é a comparação que mostra exatamente o que foi adicionado, removido ou alterado. Para aprofundar, consulte Git/GitHub.

Novo pedido do laboratório

Além de emprestar e devolver, o sistema deve permitir reservar um equipamento disponível para uma aula futura. A reserva não pode marcar o equipamento como emprestado e deve poder ser cancelada.

FAÇA AGORA — antes de autorizar qualquer edição

  1. Crie ou selecione uma branch separada.
  2. Peça apenas o plano.
  3. Revise os arquivos que o agente pretende alterar.
  4. Só depois autorize implementação.
  5. Leia o diff e execute testes antigos e novos.

PROMPT PARA O AGENTE

Antes de editar, analise o projeto e liste quais arquivos precisam mudar para implementar reserva e cancelamento de reserva. Explique por quê. Não altere nada ainda. Depois da minha aprovação, faça somente as mudanças necessárias. Preserve empréstimo, devolução e persistência existentes. Acrescente testes para as novas regras e execute também os testes antigos. Ao final, mostre resumo do diff, testes executados, riscos restantes e qualquer decisão de requisito que ainda precise de resposta humana.

PARE E CONFIRA

Não aceite “concluído” como evidência. A evidência é: escopo compreendido, diff revisado e testes executados.

16. Laboratório final — implemente a reserva sem terceirizar a decisão

Agora você assume o fluxo completo. Cada etapa produz algo que precisa ser entendido antes da próxima.

Etapa A — escreva as regras antes da IA

FAÇA AGORA: escreva com suas palavras quando uma reserva pode ser criada, o que acontece se o equipamento já estiver emprestado ou reservado e como uma reserva é cancelada. Pare aqui antes da Etapa B.

Etapa B — peça perguntas sobre lacunas

Estas são minhas regras de reserva. Antes de propor código, identifique no máximo cinco decisões que ainda estejam ambíguas e que possam alterar a implementação. Não invente respostas para elas.

PARE E CONFIRA: responda você mesmo às ambiguidades relevantes. A IA não decide a regra do laboratório.

Etapa C — transforme regras em testes

FAÇA AGORA: registre pelo menos reservar disponível, impedir segunda reserva, impedir reserva de emprestado, cancelar reserva e comprovar que empréstimo/devolução continuam funcionando.

Etapa D — planeje a alteração

Com base apenas nas regras aprovadas e no projeto atual, liste arquivos e funções que precisam mudar. Preserve o restante. Não escreva código ainda.

PARE E CONFIRA: cada arquivo listado precisa ter uma justificativa ligada a uma regra.

Etapa E — implemente pouco e revise o diff

FAÇA AGORA: autorize a implementação apenas depois de entender o plano. Compare antes/depois e procure requisito novo que ninguém pediu.

Etapa F — execute os testes e investigue qualquer falha

FAÇA AGORA: rode os testes antigos e novos. Se houver falha, primeiro descubra qual regra, teste ou implementação está errada. Não peça simplesmente para “fazer passar”.

Etapa G — explique sem a IA

FAÇA AGORA: feche a conversa e responda: quais arquivos mudaram, qual estado representa uma reserva, como ela é cancelada e quais testes comprovam que as regras antigas continuam válidas?

Critério de conclusão

Você não terminou quando a ferramenta escreveu o código. Terminou quando consegue defender a mudança com requisitos, diff, testes e explicação própria.

17. Desafio de transferência — aplique o processo em um código seu

Escolha um programa pequeno que você realmente consiga executar — em Python, JavaScript, Java, VisuAlg ou outra linguagem estudada. Não copie o projeto do laboratório; transfira o método.

  1. Explique o comportamento atual sem IA.
  2. Execute e registre pelo menos dois casos reais.
  3. Peça à IA para mapear o código sem alterá-lo.
  4. Defina uma mudança pequena e escreva o comportamento esperado.
  5. Crie casos de teste antes da mudança.
  6. Peça um plano antes de pedir código.
  7. Faça ou autorize uma alteração limitada.
  8. Compare antes/depois e execute os testes.
  9. Se houver falha, investigue com evidência antes de corrigir.
  10. Explique você mesmo o que mudou e como comprovou.

Se a única explicação for “a IA fez”

Volte uma etapa. O propósito do módulo é usar IA para aumentar sua capacidade de desenvolver e revisar software — não esconder o desenvolvimento atrás da ferramenta.

O que você aprendeu neste projeto

EntenderLer código e comportamento antes de modificar.
EspecificarTransformar pedidos em regras e casos verificáveis.
AlterarMudar pouco e preservar o que já funciona.
InvestigarUsar estado, erro e testes como evidências.
ControlarRevisar contexto, dados, diff, dependências e ações da IA.

A ideia que fecha o módulo

Programar com IA não é trocar conhecimento por velocidade. É usar velocidade sem abrir mão de entendimento, evidência e controle.

Próximo passo: IA, Ética e Sociedade — quando a questão deixa de ser apenas “o software funciona?” e passa a incluir “quem é afetado, quais dados entraram e quem responde pela decisão?”.
Voltar ao painel de IA