# Só consigo programar seguindo tutorial: como ganhar autonomia?

Aprenda a conduzir uma mudança em Java: esclareça o requisito, encontre a regra no código, consulte o que falta e verifique o comportamento com testes.

Por Bruno Rana

Publicado em: 2026-11-04
Atualizado em: 2026-11-04

Artigo original: https://buildrun.com.br/blog/como-programar-sem-tutorial/

![Um caderno descreve frete grátis a partir de 100 reais; dois recibos comparam produtos de 99 com frete de 15 e produtos de 100 com frete zero.](https://buildrun.com.br/diagrams/como-programar-sem-tutorial-1-objetos.webp)

Uma mudança pequena começa pela regra e pelos resultados esperados, antes de alterar o código.

Durante a aula, você acompanha a explicação e o código parece fazer sentido. Mas, quando fecha o vídeo e tenta construir algo, não sabe por onde começar. Essa diferença pode ser frustrante, principalmente depois de dedicar bastante tempo aos estudos.

Na aula, alguém escolheu a ordem dos passos, o arquivo que precisava mudar e o momento de conferir o resultado. **Ganhar autonomia exige praticar essas decisões: escolher uma alteração pequena, investigar o código e verificar se ela resolveu o problema.** Você pode continuar consultando materiais e pedindo ajuda durante esse processo.

Não precisa abandonar os tutoriais. Precisa criar um espaço entre acompanhar uma solução e procurar a próxima: um momento em que a pergunta é sua e a resposta ainda não está pronta na tela.

## Comece com uma mudança que caiba no projeto que você conhece

Se você acabou uma aplicação de estudo, aproveite o que já funciona. Escolha uma mudança que consiga descrever em uma frase e cujo resultado possa conferir. Refazer o projeto inteiro ou acrescentar várias tecnologias cria mais decisões simultâneas do que você precisa para esse treino.

Vamos trabalhar com uma calculadora de pedido em Java. Ela soma os produtos e acrescenta R$ 15 de frete. A mudança será oferecer frete grátis quando o subtotal chegar a R$ 100. O interesse está no caminho até a solução: esclarecer a regra, encontrar onde ela deve entrar e demonstrar que funciona.

Este exercício pressupõe que você já leu programas com variáveis, arrays, condições e métodos. Se esses conceitos ainda forem novos, faça primeiro o [orçamento para começar programação do zero](https://buildrun.com.br/blog/como-comecar-programacao-do-zero/). Aqui vamos usá-los para tomar decisões sobre um código existente.

## Esclareça o que a mudança precisa fazer

“Colocar frete grátis” deixa perguntas abertas. O valor mínimo inclui o frete? A promoção vale exatamente em R$ 100? Descontos interferem no cálculo? Resolver isso antes de editar evita que uma escolha acidental no código se transforme na regra do produto.

Neste exercício, o subtotal é a soma dos preços dos produtos. A partir de R$ 100, inclusive, o frete é zero; abaixo disso, custa R$ 15. Não há descontos. Os preços já chegam como inteiros não negativos em centavos, e consideramos apenas pedidos com produtos. Usaremos valores pequenos: tanto o subtotal quanto o total com frete precisam caber em um `int`, cujo máximo é 2.147.483.647. O exemplo não verifica esse limite automaticamente.

Anote exemplos que tornem essa decisão verificável:

| Subtotal dos produtos | Frete | Total |
| --- | --- | --- |
| R$ 99 | R$ 15 | R$ 114 |
| R$ 100 | R$ 0 | R$ 100 |
| R$ 120 | R$ 0 | R$ 120 |

O total cair entre R$ 99 e R$ 100 é consequência da promoção definida. Se isso não fizer sentido para quem pediu a mudança, a conversa é sobre o requisito. Alterar a comparação por conta própria apenas esconderia a dúvida.

## Encontre o lugar da regra antes de escrever a solução

Use JDK 21 e salve o programa abaixo em `PedidoDemo.java`. No terminal aberto nessa pasta, execute `java PedidoDemo.java`. Os exemplos foram verificados com OpenJDK 21.0.2, sem dependências externas.

Ao chamar um método, você fornece valores chamados **argumentos**; aqui, o argumento será um array de preços. `return` devolve o resultado para quem fez a chamada. A palavra `static` permite chamar `calcularPedido` pela própria classe, sem criar um objeto `PedidoDemo`.

O programa usa um **record**, uma forma de reunir dados em Java. `Pedido` guarda subtotal e frete; seu método `total()` soma os dois. O método `calcularPedido` recebe um array de preços e monta esse resultado. `main` fornece os dados do exemplo e mostra o total.

```java
public class PedidoDemo {
    record Pedido(int subtotal, int frete) {
        int total() {
            return subtotal + frete;
        }
    }

    static Pedido calcularPedido(int[] precosEmCentavos) {
        int subtotal = 0;
        for (int preco : precosEmCentavos) {
            subtotal += preco;
        }
        int frete = 1500;
        return new Pedido(subtotal, frete);
    }

    public static void main(String[] args) {
        Pedido pedido = calcularPedido(new int[] {6000, 4000});
        System.out.println("Total em centavos: " + pedido.total());
    }
}
```

A saída é `Total em centavos: 11500`: R$ 100 de produtos mais R$ 15 de frete. Esse é o comportamento anterior à promoção. Executá-lo primeiro confirma um ponto de partida conhecido.

Agora acompanhe os dados. `subtotal += preco` soma cada preço ao valor acumulado. Depois da repetição, o subtotal está pronto. O frete é definido e os dois valores formam o `Pedido`. A impressão no terminal acontece depois de tudo isso.

<figure class="explainer explainer--sketch">
<img src="https://buildrun.com.br/diagrams/como-programar-sem-tutorial-2-objetos.webp" srcset="https://buildrun.com.br/diagrams/como-programar-sem-tutorial-2-objetos-420.webp 420w, https://buildrun.com.br/diagrams/como-programar-sem-tutorial-2-objetos-840.webp 840w, https://buildrun.com.br/diagrams/como-programar-sem-tutorial-2-objetos.webp 1536w" sizes="(max-width: 800px) calc(100vw - 32px), 760px" width="1536" height="1024" loading="lazy" decoding="async" alt="Etiquetas de 60 e 40 reais seguem para uma calculadora com subtotal de 100; uma lupa destaca a decisão de frete zero, antes da impressão do recibo de 100 reais.">
<figcaption>A promoção muda a escolha do frete, depois da soma dos produtos. O recibo apenas apresenta o resultado dessa decisão.</figcaption>
</figure>

A condição deve entrar quando o subtotal já existe, antes de criar o resultado. Colocá-la somente na impressão poderia mostrar uma mensagem de promoção enquanto o pedido continuasse cobrando R$ 15.

Em um projeto maior, faça esse mesmo mapa curto: de onde vem o valor, onde ele é transformado e quem recebe o resultado. Registre a versão inicial no Git ou mantenha uma cópia. Adie reorganizações de pastas e mudanças de bibliotecas para conseguir avaliar o efeito desta alteração separadamente.

## Use a documentação para resolver a dúvida que apareceu

Talvez você saiba onde mudar, mas não lembre como escrever “maior ou igual” em Java. Essa é uma consulta sobre o operador `>=`. Talvez lembre a sintaxe, mas ainda esteja somando o frete antes de comparar. Nesse caso, precisa voltar ao significado de subtotal.

A seção de [operadores nos fundamentos de Java](https://dev.java/learn/language-basics/using-operators/) ajuda na primeira dúvida. A tabela de resultados ajuda na segunda. Identificar qual pergunta está aberta evita trocar uma investigação pequena por outro tutorial completo de loja.

Se pedir ajuda, mostre a tentativa e a divergência: “Com produtos de R$ 99, meu programa deu frete grátis. Comparei o total com R$ 100. Qual valor deveria representar o critério?”. Há informação suficiente para discutir o raciocínio sem alguém reconstruir o projeto por você.

Depois da consulta, volte ao arquivo e faça sua tentativa. Conseguir usar uma explicação no próprio contexto é uma parte importante da prática; ler a resposta e reconhecê-la não revela se você já consegue aplicá-la.

## Confira a regra com casos que distinguem soluções parecidas

A mudança é pequena: começar o frete em `1500` e zerá-lo quando `subtotal >= 10000`. Mas ver apenas um pedido funcionando não basta. Precisamos conferir abaixo do limite, exatamente nele e acima dele.

A versão completa abaixo inclui essas verificações. `conferir` compara o pedido calculado com o esperado e lança um `AssertionError` se houver diferença. Isso interrompe o programa e identifica o caso que falhou. É um teste local simples, sem biblioteca adicional.

```java
public class PedidoDemo {
    record Pedido(int subtotal, int frete) {
        int total() {
            return subtotal + frete;
        }
    }

    static Pedido calcularPedido(int[] precosEmCentavos) {
        int subtotal = 0;
        for (int preco : precosEmCentavos) {
            subtotal += preco;
        }
        int frete = 1500;
        if (subtotal >= 10000) {
            frete = 0;
        }
        return new Pedido(subtotal, frete);
    }

    static void conferir(String caso, int[] precos, Pedido esperado) {
        Pedido atual = calcularPedido(precos);
        if (!atual.equals(esperado)) {
            throw new AssertionError(caso + ": " + atual);
        }
    }

    public static void main(String[] args) {
        conferir("abaixo", new int[] {9900}, new Pedido(9900, 1500));
        conferir("um centavo antes", new int[] {9999},
                 new Pedido(9999, 1500));
        conferir("no limite", new int[] {6000, 4000},
                 new Pedido(10000, 0));
        conferir("acima", new int[] {12000}, new Pedido(12000, 0));
        System.out.println("Regra de frete verificada");
    }
}
```

Substitua o conteúdo de `PedidoDemo.java` por essa versão e execute novamente. A saída deve ser `Regra de frete verificada`. O `equals` de um record compara seus componentes, por isso o teste detecta diferenças tanto no subtotal quanto no frete.

<figure class="explainer explainer--sketch">
<img src="https://buildrun.com.br/diagrams/como-programar-sem-tutorial-3-objetos.webp" srcset="https://buildrun.com.br/diagrams/como-programar-sem-tutorial-3-objetos-420.webp 420w, https://buildrun.com.br/diagrams/como-programar-sem-tutorial-3-objetos-840.webp 840w, https://buildrun.com.br/diagrams/como-programar-sem-tutorial-3-objetos.webp 1536w" sizes="(max-width: 800px) calc(100vw - 32px), 760px" width="1536" height="1024" loading="lazy" decoding="async" alt="Três pranchetas conferem o frete: subtotal de 99,99 reais mantém 15 de frete; produtos de 60 e 40 atingem 100 e zeram o frete; subtotal de 120 também zera o frete.">
<figcaption>O caso com dois produtos verifica a soma. O caso exato verifica se a promoção inclui o limite.</figcaption>
</figure>

Troque `>=` por `>` e execute. O caso `no limite` deve falhar. Restaure o operador. Depois experimente comparar `subtotal + frete >= 10000`: o caso `abaixo` deve falhar, porque a implementação está contando o transporte para conceder o benefício. Restaure o código novamente.

Esses experimentos mostram por que escolhemos os casos. Eles distinguem a regra combinada de duas implementações plausíveis, mas erradas. Ainda não tratamos carrinho vazio, entradas inválidas, descontos ou cobrança real; isso precisaria de outros requisitos e testes.

## Faça uma segunda mudança com menos orientação

Agora permita que o valor mínimo da promoção seja informado ao método. Antes de escrever, escolha dois limites diferentes e calcule exemplos no papel. Reaproveite os testes anteriores com limite de R$ 100 e acrescente os novos. Essa variação exige decidir como passar a informação sem mudar a regra por acidente.

Ao terminar, explique o caminho sem ler o artigo: qual era o comportamento, qual decisão faltava, onde você alterou e como verificou. Se uma parte não sair, você encontrou um ponto específico para revisar.

Guarde também a dúvida que resolveu e a fonte que consultou. Esse registro permite retomar o raciocínio e mostrar a evolução de um projeto. O [roteiro de portfólio backend além do tutorial](https://buildrun.com.br/blog/portfolio-backend-alem-do-tutorial/) ajuda a transformar essas mudanças em uma demonstração que você consegue sustentar.

Se percebeu lacunas nos fundamentos e quer uma sequência acompanhada, compare os [conteúdos da formação Build & Run](https://buildrun.com.br/blog/formacao-buildrun/) com o que travou durante a tentativa. A próxima aula pode responder a uma necessidade que você já reconhece no seu código.

Referências consultadas em 04/11/2026: [fundamentos de Java](https://dev.java/learn/language/constructs/basics/), [classes record no JDK 21](https://docs.oracle.com/en/java/javase/21/language/records.html) e [execução de arquivos no JDK 21](https://docs.oracle.com/en/java/javase/21/docs/specs/man/java.html).
