Organização de um pequeno programa
Objetivo da aula
Combinar entrada, regras, funções, coleções, persistência e ponto de entrada.
Regra desta aula: vamos assumir que você nunca viu este assunto antes. Nenhum termo importante será usado sem explicação e todo exemplo deve ser entendido linha por linha, não apenas copiado.
Começando do zero
Um pequeno programa fica mais fácil de manter quando separamos interface, regras e persistência. A interface conversa com o usuário; as regras transformam dados; a persistência carrega e salva. Essas camadas não precisam virar uma arquitetura complexa: bastam funções e arquivos com responsabilidades claras.
Uma imagem mental para entender
Imagine uma pequena loja. O atendente fala com o cliente; o setor de estoque aplica regras; o arquivo registra movimentações. Se o atendente também precisa conhecer cada detalhe do arquivo e cada fórmula, qualquer mudança se espalha. Separar papéis reduz acoplamento.
Conceitos essenciais, sem pular etapas
Interface
Recebe entrada e apresenta saída. Em nosso projeto terminal, isso inclui input(), menus e mensagens.
Regras
Funções que calculam, validam, filtram ou alteram estruturas de dados sem depender diretamente da interação.
Persistência
Funções que leem e escrevem arquivo, como JSON.
Coordenação
Uma função main() ou equivalente liga as partes: carrega dados, mostra menu, chama regras e salva quando necessário.
Fluxo de dados explícito
Dados entram em funções por parâmetros e saem por return ou mutações intencionais, em vez de depender de muitas variáveis globais.
Modelo mental
CARREGAR → INTERFACE COLETA → REGRAS PROCESSAM → INTERFACE MOSTRA → PERSISTÊNCIA SALVA
Exemplo 1 — primeiro veja o programa inteiro
def adicionar_tarefa(tarefas, titulo):
tarefa = {"titulo": titulo, "concluida": False}
tarefas.append(tarefa)
def contar_concluidas(tarefas):
total = 0
for tarefa in tarefas:
if tarefa["concluida"]:
total = total + 1
return total
tarefas = []
adicionar_tarefa(tarefas, "Estudar funções")
print("Concluídas:", contar_concluidas(tarefas))
Agora vamos ler linha por linha
adicionar_tarefacontém uma regra de criação de registro.contar_concluidascalcula um resumo e retorna valor.- O pequeno trecho principal coordena chamadas.
- Em um programa completo, entrada do usuário e arquivo podem ser adicionados sem misturar suas regras em todas as funções.
Saída esperada
Concluídas: 0
Exemplo 2 — o mesmo conceito em outra situação
def main():
tarefas = []
# 1. carregar dados
# 2. mostrar menu
# 3. executar ação escolhida
# 4. salvar alterações
print("Aplicação iniciada")
if __name__ == "__main__":
main()
Este esqueleto mostra coordenação sem implementar detalhes. Antes de escrever centenas de linhas, desenhe o fluxo e atribua cada responsabilidade a uma função ou módulo.
Experimento guiado
Não pule esta parte. Programação só começa a fazer sentido quando você prevê um resultado, executa e compara a previsão com o que realmente aconteceu.
- Pegue um programa monolítico e marque linhas de interface, regra e persistência.
- Extraia um cálculo para função pura ou quase pura.
- Centralize chamadas em
main(). - Desenhe em papel setas mostrando de onde os dados vêm e para onde vão.
Mini desafio
Desenhe uma arquitetura mínima para um cadastro de tarefas: app.py para interface, core.py para regras e dados.json para persistência. Escreva a responsabilidade de cada parte.
Solução comentada
# app.py: entrada, menu e mensagens
# core.py: adicionar, concluir, remover e calcular estatísticas
# dados.json: estado persistido entre execuções
# main(): coordena carregar -> interagir -> salvar
Depois de executar a solução, altere pelo menos um valor e explique por que o novo resultado mudou. Se você só copiou e não consegue explicar cada linha, refaça o desafio em uma versão menor.
Erros comuns e por que acontecem
- Criar um arquivo com centenas de linhas misturando todas as responsabilidades.
- Fazer funções de regra chamarem
input()diretamente e dificultar testes. - Usar globais para compartilhar todo o estado.
- Separar arquivos demais sem necessidade e transformar um programa pequeno em labirinto.
Cheque se você realmente entendeu
Qual papel da interface?
Resposta: Receber entrada e apresentar saída.
Qual papel da persistência?
Resposta: Carregar e salvar dados entre execuções.
Por que regras separadas são mais testáveis?
Resposta: Porque podem receber dados diretamente e retornar resultados sem depender do terminal ou de arquivos.
Resumo em linguagem simples
Nesta aula, o ponto central foi Organização de um pequeno programa. Tente explicar o modelo CARREGAR → INTERFACE COLETA → REGRAS PROCESSAM → INTERFACE MOSTRA → PERSISTÊNCIA SALVA sem olhar a tela. Depois, escreva um exemplo próprio menor que os apresentados. Esse exercício de explicação é parte do aprendizado, não um extra.