DEV Community

Cover image for Como uma planilha bagunçada virou o Nero: aprendendo PHP ao resolver um problema de verdade

Como uma planilha bagunçada virou o Nero: aprendendo PHP ao resolver um problema de verdade

O problema não era meu

Minha esposa organiza as notas e os certificados dos cursos livres em uma planilha. Funciona, mas é aquele tipo de "funciona" que exige lembrar em qual aba está cada coisa, recalcular médias manualmente sempre que sai uma nota nova e vasculhar uma pasta cheia de PDFs quando alguém pede um certificado.

Não era algo quebrado o suficiente para virar prioridade. Era apenas um atrito pequeno e constante.

Até que, em um belo dia, ela lançou um:

Poxa, queria que fosse mais fácil organizar tudo isso.

sutileza nunca foi o forte da minha digníssima e após isso eu fiquei com uma pulga atrás da minha orelha:

Eu tinha três opções.

A primeira era ajustar a planilha dela no Excel, organizando as fórmulas para que tudo fosse calculado automaticamente. Funcional, porém sem graça.

A segunda era procurar uma solução pronta. Talvez fosse a melhor opção, considerando que provavelmente existem várias ferramentas por aí que fazem algo parecido.

A terceira, e talvez a pior de todas, pensando de forma puramente lógica, era criar um aplicativo do zero, exatamente do jeito que ela queria. Seria a opção mais difícil e demorada.

Adivinha qual eu escolhi? Kkk.

Eu já queria aprender PHP na prática, sem framework, e agora tinha uma ótima desculpa. Foi então que percebi que aquele era o problema certo para isso.

Eu não precisava inventar um projeto de brinquedo. Bastava resolver algo que já incomodava uma pessoa que eu conhecia bem.

Foi assim que nasceu o Nero. Estou assistindo a Black Clover e achei o nome apropriado. Podem me julgar.

O que o Nero faz

Nada revolucionário. Ele faz o básico:

Interface inicial

  • Cadastra o curso, incluindo instituição, nome, quantidade de períodos e período atual. Os períodos são gerados automaticamente, sem que o usuário precise criar um por um.
  • Cada período possui disciplinas, e cada disciplina possui avaliações.
  • Calcula quanto o aluno precisa tirar nas avaliações restantes para ser aprovado, considerando as notas que já obteve.
  • Permite cadastrar cursos livres e atividades extracurriculares, com upload do certificado em PDF, resolvendo exatamente uma das dores da planilha: não precisar mais vasculhar pastas em busca de arquivos.
  • Exibe um dashboard com média geral, disciplinas pendentes e próximas avaliações.

A conta de "quanto falta" é a parte de que mais me orgulho, porque, no fundo, é uma regra de três disfarçada de código:

private static function calcularRestante(
    array $disciplina,
    bool $usaPeso,
    float $notaMinima,
    float $somaNotaPeso,
    float $somaPeso,
    int $quantidadeFeitas
): array {
    // ... (versão com peso omitida)

    $qtdPrevista = $disciplina['qtd_avaliacoes_previstas'] ?? null;

    if ($qtdPrevista === null) {
        return [null, null]; // ainda não configurado
    }

    $restantes = $qtdPrevista - $quantidadeFeitas;

    if ($restantes <= 0) {
        return [null, (float) $restantes]; // as avaliações já acabaram
    }

    $necessaria = (
        $notaMinima * $qtdPrevista - $somaNotaPeso
    ) / $restantes;

    return [$necessaria, (float) $restantes];
}
Enter fullscreen mode Exit fullscreen mode

É simples: pega a média mínima, multiplica pela quantidade total de avaliações, subtrai o que já foi somado e divide pela quantidade de avaliações restantes.

O primeiro rascunho dessa função, feito sem pensar muito, misturava esse cálculo com uma simulação hipotética de "e se eu tirasse a nota X?", sem qualquer vínculo com as avaliações que realmente faltavam.

O resultado ficou confuso.

Precisei voltar para o mundo das ideais até que a lógica correspondesse à pergunta que a pessoa realmente faz:

Quanto eu preciso tirar para passar?

O perrengue técnico

Esse tipo de problema técnico não é exatamente novidade para mim. Mesmo assim, por alguma razão, minha mente demorou um pouco para identificar a causa.

O banco "sumiu" — spoiler: era IPv6

Primeiro deploy, primeira tentativa de login:

SQLSTATE[08006] connection to server at "db.xxxxx.supabase.co"
(2600:1f11:...) port 5432 failed: Network is unreachable
Enter fullscreen mode Exit fullscreen mode

O host de conexão direta do Supabase resolvia apenas para IPv6.

Quando o ambiente em que a aplicação está rodando não possui saída IPv6, algo comum em containers e em vários provedores, a conexão simplesmente não acontece, mesmo que o usuário e a senha estejam corretos.

Isso causava um erro bastante curioso: eu conseguia fazer login, mas logo em seguida recebia uma tela branca de erro.

A solução foi trocar a conexão direta pelo connection pooler, o Supavisor, que é compatível com IPv4:

# antes: conexão direta, apenas IPv6
host: db.xxxxxxxxxxxxxxxx.supabase.co

# depois: pooler, compatível com IPv4
host: aws-0-<região>.pooler.supabase.com
port: 6543   # transaction mode, ou 5432 para session mode
user: postgres.<project-ref>   # repare no sufixo
Enter fullscreen mode Exit fullscreen mode

Outro detalhe que me pegou: no pooler, o usuário precisa incluir o identificador do projeto.

Apenas trocar o host não foi suficiente. A autenticação começou a falhar de uma maneira completamente diferente, até que percebi a ausência desse sufixo.

Onde o Nero está agora

Hoje, o Nero tem um único usuário real utilizando o sistema no dia a dia: minha esposa.

São as notas dela, os certificados dela e o histórico dela.

Pode parecer pouco, mas é exatamente por isso que o projeto tem mais cara de produto do que de exercício. Cada decisão de experiência do usuário nasce de uma reclamação real:

Isso ficou estranho.

Não é assim que eu penso essa conta.

As decisões não vêm apenas de suposições minhas.

O projeto começou como uma desculpa para aprender PHP sem trocar de tecnologia no meio do caminho. Ele continua sendo isso.

Mas agora também é uma ferramenta que resolve um problema de verdade para uma pessoa de verdade.

No fim das contas, isso me ensinou muito mais sobre construir software do que qualquer tutorial teria ensinado sozinho.


*Stack: PHP puro, sem framework; PostgreSQL via Supabase; deploy no Render.

Top comments (0)