Primeiros passos no desenvolvimento Java em 2023: um guia particular
Tags: java, beginners, productivity, tooling
Published: 2023-01-19 17:25:36

Este post foi criado com a ideia de ser quase uma tradução [do guia](https://www.morling.dev/blog/getting-started-with-java-development-2023/) publicado pelo [Gunnar Morling](https://twitter.com/gunnarmorling), e considerando algumas modificações com base na minha experiência também. Deixando bem claro: esta versão é baseada no post do Gunnar, com a **minha visão** e sem nenhuma relação ou endosso do autor.

## A Linguagem

A linguagem Java aparece no topo dos rankings divulgados como [TIOBE index](https://www.tiobe.com/tiobe-index/) e [StackOverflow survey](https://survey.stackoverflow.co/2022/#technology-most-popular-technologies). 

Independentemente de qualquer pesquisa, a linguagem é bastante madura pelos seus 27 anos, é plenamente ativa na comunidade (com inúmeros frameworks e bibliotecas) e uma nova versão é lançada a cada 6 meses, sendo que uma nova versão LTS (*long-term support*) é declarada a cada 2 anos.

Além da linguagem, a JVM (Java Virtual Machine) é muito reconhecida como uma das principais máquinas virtuais para o tempo de execução.

O ecossistema em torno da linguagem é completo, passando por sistemas desktop, linha de comando, aplicações web, webservices, APIs, até plataformas de stream-processing e armazenamento de dados (big data).

Novidades cobiçadas estão em desenvolvimento, como [threads virtuais leves](https://openjdk.org/projects/loom) (*Project Loom*), melhorias na [integração com código nativo](https://openjdk.org/projects/panama/) (*Project Panama*), [value objects e user-defined primitives](https://openjdk.org/projects/valhalla/) (*Project Valhalla*), entre outros, e é justamente por isso que o Java está se tornando uma excelente ferramenta para resolver um número cada vez maior de tarefas de desenvolvimento de software.

## Onde Estamos

A imensa quantidade de opções acumuladas durante quase 3 décadas pode ser um desafio inerente para pessoas que estão começando sua carreira agora. Qual versão devo utilizar? Por que tantas opções? Como instalar 2+ versões sem conflitos? Quais ferramentas (IDE) utilizar? Todas essas (e qualquer outra) perguntas possuem mais de uma opção como resposta, e isso pode acabar sobrecarregando a carreira de uma pessoa nova na tecnologia Java.

Muitas ferramentas famosas no passado já praticamente não existem mais, outras evoluíram para novas versões. Um ponto de atenção para esses casos, pois na Internet tudo está disponível e pode ser difícil identificar o que é relevante do que caiu em desuso.

## Guia Opinativo

A ideia deste post é servir como um guia opinativo para as pessoas que estão começando no desenvolvimento Java em 2023, ajudando você nos primeiros passos dessa plataforma incrível. 

Lembre-se que as decisões são pessoais, são as minhas recomendações e elas podem ser diferentes das suas, sem nenhum problema.

> Assim como Gunnar deixou bem claro que as coisas que ele recomendou podem não ser exatamente as melhores, eu também não tenho a intenção de ser dono da verdade. A minha ideia também é de ajudar: seja na tradução livre do post original, seja nas alterações pontuais que eu tomei a liberdade de fazer - e porque eu concordo com todo o post dele. Conforme a experiência do desenvolvedor vai tomando forma, você começa a formar a sua opinião e, nesse momento, já poderá seguir com suas decisões, sem depender de guias e afins.

## Ecossistema Java

Num primeiro momento, pode ser confuso para entender o que Java realmente é.

### A linguagem de programação Java

É uma linguagem de programação orientada a objetos, com tipagem estática e de uso geral (com algumas pitadas de linguagem funcional). O código é compilado para um byte-code portátil que é interpretado por uma máquina virtual, ou seja, pode ser executado em diversos sistemas operacionais diferente de onde foi compilado inicialmente.

### A Plataforma Java

[*O universo Java é um vasto conjunto de tecnologias, composto por três plataformas principais que foram criadas para segmentos específicos de aplicações.*](https://pt.wikipedia.org/wiki/Java_(plataforma_de_software)).

Os elementos chave aqui são o compilador Java (javac); a máquina virtual (JVM) e a biblioteca padrão da linguagem. O objetivo deste post é a versão Java Standard Edition (SE), as demais Java Micro Edition (ME) e Jakarta Enterprise Edition (EE) não serão discutidas aqui.

Muitas outras linguagens podem ser executadas na JVM além da própria Java como, por exemplo, Kotlin, Groovy, Scala.

### A Máquina Virtual Java (JVM)

É uma máquina virtual responsável por executar os programas escritos em Java (ou melhor, o byte-code), ou seja, cuidando das tarefas como carregar o byte-code e verificar sua precisão, compilando esse byte-code em código nativo usando um compilador just-in-time (JIT), gerenciamento de memória automatizado via coleta de lixo (garbage collector), isolamento entre diferentes componentes, fornecendo dados para diagnóstico em tempo de execução etc. Existem várias implementações da JVM, como [HotSpot](https://openjdk.org/groups/hotspot/), [OpenJ9](https://www.eclipse.org/openj9/), [Azul Zulu](https://docs.azul.com/core/), entre outras.

### O Java Development Kit (JDK)

Um pacote de ferramentas para desenvolvimento e execução de aplicações Java.

### OpenJDK

Uma implementação open-source do Java SE. Também é o nome da comunidade open-source que cuida dessa implementação.

### O Java Community Process (JCP)

Um grupo para desenvolvimento de novas especificações no mundo Java, incluindo as diferentes versões do Java.


## 📦 Distribuição

A plataforma Java é mantida pelo projeto open-source [OpenJDK](https://openjdk.org/). Similar ao Linux, múltiplos fornecedores disponibilizam binários para o projeto, incluindo Amazon, a fundação Eclipse, Microsoft, Oracle e Red Hat. Essas distribuições se diferenciam por aspectos como suporte comercial, plataformas suportadas, algumas com diferentes garbage collectors. Muitos fornecedores disponibilizam uma versão gratuita também. Portanto, qual devo utilizar?

No início, a diferença não importa tanto e **a sugestão é começar com [Eclipse Temurin](https://adoptium.net/)**. Essa versão é suportada pelo grupo de empresas como Google, Red Hat, Microsoft, Alibaba, Azul e outras. Você pode baixá-lo e usá-lo gratuitamente, contém tudo o que você precisa, é compatível com o Test Compatibility Kit (TCK) da JDK - ou seja, é uma JVM "homologada" - e, caso seja necessário, tem suporte comercial disponível por diferentes fornecedores.


## 📆 Versão

Uma nova versão do Java é lançada a cada 6 meses. A versão atual no momento da escrita deste post sendo a [Java 19](https://jdk.java.net/19/). Versões específicas são consideradas de suporte prolongado (*long-term support* ou LTS), em que cada fornecedor responsável pela JVM dá manutenção por alguns anos. **A versão LTS, atualmente, é a Java 17 e a recomendação é escolher esta versão**, neste momento.

Existem versões mais novas atualmente (18 e 19) que não são LTS e possuem funcionalidade interessantes, porém pode ser um desafio manter suas aplicações atualizadas de forma sustentável, sem contar que muitas dessas novidades ainda podem estar em fase de testes (*preview*) ou incubadas - você acabará não utilizando isso em produção. A recomendação, neste caso, é se aventurar nessas versões quando você possuir um pouco mais de experiência.

Caso alguma biblioteca de terceiros ainda não seja suportada pelo Java 17, deve-se procurar uma versão LTS anterior, que no caso é o Java 11. Tente evitar a utilização de versões não LTS, pois elas não têm compromisso com manutenção por muito tempo, ou seja, você pode estar com algum problema de segurança sem nenhuma visibilidade de correção ou bugs. Uma observação importante: não utilize o Java 8 (ou 1.8, como era chamado na época), que seria a versão LTS antes da 11, pois ela já está muito antiga.

## 🔧 Instalação

Existem algumas formas para instalar a versão escolhida. Geralmente, você encontrará um pacote que você pode instalar a partir do site do fornecedor. Você também poderia utilizar uma versão disponível de algum gerenciador de pacotes da sua distribuição Linux.

**A minha recomendação é iniciar por uma forma mais simples que é por meio do [SDKMan](https://sdkman.io/)**. Esta ferramenta o auxilia na instalação de softwares (SDKs) e demais ferramentas necessárias para o desenvolvimento. O SDKMan também gerencia futuras instalações, assim como múltiplas versões instaladas facilmente e sem conflitos.

Se você já possui o SDKMan instalado, faça isto para obter a versão 17:
```bash
$ sdk install java 17.0.5-tem # Instalar
$ sdk use java 17.0.5-tem # Selecionar
$ java --version # Verificar versão

openjdk 17.0.5 2022-10-18
...
```

> **Instalação no Windows**
> SDKMan é feito em bash, portanto, se você utiliza Windows, você precisará do Windows Subsystem for Linux (WSL) ou do Cygwin antes. Outra opção seria utilizar o gerenciador de pacotes [winget](https://github.com/microsoft/winget-cli) ou baixar o pacote diretamente do site do fornecedor.


## 💡 Seu Primeiro Programa

Após a instalação do Java, vamos criar o primeiro programa. Java é uma linguagem primariamente orientada a objetos, então tudo em Java é definido utilizando classes, que possuem atributos (representam o seu estado) e métodos (permitem alterar o estado interno). Como de costume, seu primeiro *Hello world!*

```java
public class HelloWorld { // #1
  public static void main(String... args) { // #2
    System.out.println("Hello world!"); // #3
  }
}
```

1. A classe `HelloWorld` deve ser especificada num arquivo com o mesmo nome (`HelloWorld.java`);
2. O método `main()` é o ponto de entrada de um programa Java;
3. O método `println()` imprime o texto na saída padrão (*stdout* ou *standard output*).

O código Java é compilado para um arquivo `class` e que posteriormente é carregado na JVM para ser executado. Geralmente, isto é feito em duas etapas: 1) compilar utilizando o *javac*; 2) executar o binário com o *java*. Para simplificar, é possível realizar os dois comandos de uma só vez:

```bash
$ java HelloWorld.java
Hello world!
```

Para fins didáticos e uma exploração rápida existe o [jshell](https://docs.oracle.com/en/java/javase/17/docs/specs/man/jshell.html), que é um REPL (Read-Evaluate-Print-Loop). É possível executar comandos mais simples sem a necessidade de declaração de pacotes, classes etc.:

```bash
$ jshell

jshell> System.out.println("Hello World");
Hello World
```

Similar ao jshell existe também o [jbang](https://www.jbang.dev/), que é um pouco mais avançado, possibilitando a importação de bibliotecas terceiras.

## 📚 Aprendendo a Linguagem

Fornecer uma introdução para todas as funcionalidades básicas da linguagem Java está além do escopo deste post. Para realmente aprender a linguagem e seus detalhes, minha recomendação é pegar um bom livro, um bom café (vários) e estudar, seguindo suas preferências.

Algumas recomendações de livros populares: ["Head First Java, 3rd Edition"](https://www.oreilly.com/library/view/head-first-java/9781492091646/), escrito pela Kathy Sierra, Bert Bates, Trisha Gee, complementado por ["The Well-Grounded Java Developer, 2nd Edition"](https://www.manning.com/books/the-well-grounded-java-developer-second-edition), por Benjamin Evans, Jason Clark e Martijn Verburg. Uma leitura obrigatória para aprimorar suas habilidades em Java é o ["Effective Java, 3rd Edition"](https://www.oreilly.com/library/view/effective-java-3rd/9780134686097/) por Joshua Bloch. A última edição foi escrita com base no Java 9, porém o conteúdo não fica preso à versão em si e se aplica até nas versões atuais.

Se você não é do estilo de comprar e ler livros, existe o guia ["Learn Java"](https://dev.java/learn/) do site [dev.java](https://dev.java). Existem vários materiais sobre a linguagem, sobre a JVM e suas ferramentas mais importantes com muitos detalhes.

Outra opção que pode interessar muita gente é estudar via cursos. Aqui no Brasil temos a Alura, com diversos cursos bons, inclusive uma [carreira de Java](https://www.alura.com.br/cursos-online-programacao/java). Outra opção que costuma ter descontos e preços acessíveis é na [Udemy](https://www.udemy.com/courses/search/?src=ukw&q=java).

Se você gosta de certificação existe a ["Oracle Certified Professional: Java SE 17 Developer"](https://education.oracle.com/products/trackp_OCPJSE17). Eu recomendo que você trabalhe pelo menos uns 2 anos com a linguagem, para se ambientar, e também estude durante este período, pois a certificação é relativamente difícil e com bastantes pegadinhas.


## 👷‍♀️ Build Tool

Após os primeiros passos na linguagem, você precisará de uma ferramenta de automação da compilação do projeto. Essas ferramentas ajudam não apenas na compilação, como no gerenciamento das dependências (bibliotecas terceiras que você utilizará), execução e validação dos testes automatizados, montagem dos artefatos (arquivos `.jar`), entre outras. Existem plugins bem interessantes que [analisam seu código](https://spotbugs.github.io/), validando bugs e sugerindo formas melhores de escrever a mesma lógica. Aqui cabe uma observação importante: aprender com exemplos também é uma forma relevante de absorver conhecimento e que já me ajudou muito.

As ferramentas mais conhecidas incluem [Apache Maven](https://maven.apache.org/), [Gradle](https://gradle.org/) e [Bazel](https://bazel.build/docs/bazel-and-java).

**Minha recomendação é escolher o Maven.** É a ferramenta mais utilizada (desde projetos simples até complexos) e é relativamente simples de entender. Para instalar, basta um `sdk install maven` utilizando o SDKMan. A estrutura de um projeto Maven deve seguir algumas premissas, o que também significa que você não precisa ficar pensando em muitos detalhes específicos, o que é bom quando se está começando.

Maven suporta arquétipos, como se fossem modelos prontos para serem utilizados. Por exemplo: 

```bash
mvn archetype:generate -B \
  -DarchetypeGroupId=org.moditect.ossquickstart \
  -DarchetypeArtifactId=oss-quickstart-simple-archetype \
  -DarchetypeVersion=1.0.0.Alpha1 \
  -DgroupId=com.example.demos \
  -DartifactId=fancy-project \
  -Dversion=1.0.0-SNAPSHOT \
  -DmoduleName=com.example.fancy
```

Uma IDE (abordaremos no próximo tópico) vai facilitar a criação de um projeto, seja com Maven ou Gradle. Ou seja, não se apegue tanto ao comando acima.

Uma funcionalidade menos conhecida e útil é o [Maven Daemon](https://github.com/apache/maven-mvnd), que auxilia drasticamente na velocidade das execuções, mantendo um processo rodando em segundo plano e evitando o custo de iniciar repetidamente o ambiente necessário. Para instalar, basta um `sdk install mvnd`.

A ferramenta Gradle também é popular e poderosa, tem muita flexibilidade e funcionalidades interessantes como compilação incremental (ou *compilation avoidance*, que, de forma inteligente, compila apenas as partes que foram modificadas). São funcionalidades interessantes, porém mais avançadas.

## 📝 Editor / IDE

Muitos desenvolvedores (não apenas no mundo Java) adoram brigar pelo melhor build tool, a melhor distribuição Linux... e com editor não poderia ser diferente. Ou seja, facilmente muitas opiniões diferentes surgirão neste ponto. Além dos editores, existem também as Integrated Development Environment ou IDEs.

**Minha sugestão é utilizar o [IntelliJ IDEA](https://www.jetbrains.com/idea/)**. É uma IDE relativamente pesada, mas te dará suporte valioso em todas as etapas do desenvolvimento: desde a criação do projeto, com o versionamento (git), com os testes automatizados, com as execuções do Maven/Gradle, com sugestões para simplificar e/ou melhorar seu código, com refatorações, suporte a debugging, ou seja, vale a pena. Vale citar que existe a versão Community (free) e também a Ultimate (paga). Reserve um tempo para aprender e se acostumar com as teclas de atalho, pois elas te salvarão muito tempo no dia a dia.

Existem outras IDEs igualmente famosas: [Eclipse IDE](https://www.eclipse.org/ide) e [NetBeans](https://netbeans.apache.org/).

Como não poderia deixar de ser, existem opções bastante leves, como é o caso do [VSCode](https://code.visualstudio.com/) com o auxílio de [plugins para suportar a linguagem Java](https://code.visualstudio.com/docs/languages/java). Esta seria a minha segunda opção depois do IntelliJ.

## 🧱 Bibliotecas

O ecossistema de bibliotecas de terceiros disponíveis é o que torna a linguagem Java tão forte: certamente você encontrará uma opção (biblioteca ou framework) pronta para ser utilizada em todas as tarefas que você imaginar, e geralmente é uma opção open-source.

No entanto, tome cuidado! Seja ponderado na escolha de quais bibliotecas você realmente necessita para importar ao seu projeto. Muitas opções também existem na própria linguagem, sem a necessidade de importar uma nova dependência.

Adicionar uma dependência ao seu projeto deve ser sempre uma decisão consciente. Sem um controle disso, você encontrará conflitos entre as versões transitivas (ou seja, dependências das dependências), aumentará a complexidade do seu projeto (mantendo tudo atualizado, o que é sempre o recomendado), estará mais sujeito a vulnerabilidades etc. Algumas vezes, é melhor codificar algo no próprio projeto, ou até mesmo copiar uma parte de uma biblioteca que você necessita - desde que a licença permita.

Algumas bibliotecas famosas que você encontrará em muitos projetos Java:
- [JUnit](https://junit.org/junit5/) para testes unitários;
- [slf4j](https://www.slf4j.org/) para padronização dos logs;
- [Jackson](https://github.com/FasterXML/jackson) para lidar com JSON;
- [Testcontainers](https://www.testcontainers.org/) para facilitar testes de integração com Docker;

A lista [awesome-java](https://github.com/akullpp/awesome-java) é um ponto de partida para conhecer muitas outras opções de bibliotecas famosas.

A grande maioria das bibliotecas está disponível no repositório do [Maven Cental](https://search.maven.org/). Todas as ferramentas de compilação (build tools) são integradas com esse repositório. O site [MVN Repository](https://mvnrepository.com/) facilita na busca e detalhes das bibliotecas, com suas versões e suas dependências. Você também poderá chegar num ponto em que é necessário publicar artefatos (bibliotecas) internos na sua organização. Isto é bastante comum e possível com o uso de servidores como [Nexus](https://www.sonatype.com/new/products/nexus-repository) ou [Artifactory](https://jfrog.com/artifactory/). Também existem opções na nuvem, como o [AWS CodeArtifact](https://aws.amazon.com/codeartifact/).

## 🐢 Frameworks de Aplicação

Muitos sistemas empresarias são construídos em cima de um framework que provê suporte para estruturar seu código via injeção de dependência, auxilia perfeitamente no gerenciamento das versões das dependências terceiras (no Maven, BOM ou *Bill of Materials*), ajuda nos testes facilitando a criação de mocks das APIs e clientes, entre outros.

Como já deve ser esperado, aqui existem várias opções, em que todas são conhecidas e nenhuma é a melhor em todos os quesitos. 

As principais opções são [Spring Boot](), [Quarkus](), [Micronaut](), [Helidon](), [Jakarta EE](). **Minha recomendação aqui é escolher o Spring Boot**, pelo amplo suporte e maturidade. Quarkus e Micronaut são nomes mais novos no mercado e certamente merecem uma chance com você: eles foram criados com o intuito de levar o Java para a nuvem (cloud computing), ou seja, prezam pela simplicidade, evitam ao máximo - ou até proíbem - reflection, tudo isso com o objetivo de suportar a GraalVM (basicamente, código Java compilado nativamente).

O jeito mais simples para começar um projeto utilizando Spring Boot é pelo [Spring Initializr](https://start.spring.io/). Basta selecionar as opções desejadas, as dependências que você gostaria de utilizar e é isso: o download de um arquivo zip será realizado, pronto para ser importado na sua IDE.

## 🐳 Container Base Image

Quando você está trabalhando num ambiente corporativo, provavelmente o projeto será publicado no formato de container image, facilitando assim a publicação (deploy) num ambiente de execução como Docker ou Kubernetes.

Aqui sugiro seguir com a mesma versão do Java que recomendei para instalar localmente: seguir com a imagem do [Eclipse Temurin](https://hub.docker.com/_/eclipse-temurin/), isto é, `eclipse-temurin:17` para Java 17. Sempre tenha a preocupação de manter sua imagem atualizada, assim como foi recomendado com as suas dependências.

Evite utilizar a imagem [OpenJDK](https://hub.docker.com/_/openjdk), pois ela está oficialmente depreciada e não é mais recomendada para produção.

## 🤓 Como se manter atualizado

Esse ecossistema não vai parar de trazer novidades e você precisará se manter atualizado sobre tudo o que gira em torno do Java.

Algumas fontes que utilizo para me manter atualizado e aprender com o que tem acontecido na comunidade:
- [Java News](https://dev.java/news/)
- [Inside.java](https://inside.java/)
- [Awesome Java Weekly Newsletter](https://java.libhunt.com/newsletter): uma coletânea dos principais artigos e novidades da semana;
- Reading list curada pelo [Rodrigo Graciano](https://graciano.dev/)
- [InfoQ Java](https://www.infoq.com/java)
- o próprio [Gunnar Morling](https://twitter.com/gunnarmorling) no Twitter;
- [Siva](https://twitter.com/sivalabs) (@sivalabs) no Twitter: bastante conteúdo, principalmente sobre Spring;

## 🔭 Próximos Passos

Espero que este guia tenha servido para ajudá-lo de alguma forma e que sirva para uma jornada de sucesso no mundo Java. De qualquer forma, este guia é apenas o começo. Dependendo das suas necessidades e requisitos, tem uma enorme quantidade de opções para avaliar.

- Construir binários nativos utilizando [GraalVM](https://www.graalvm.org/), que permite inicialização rápida (poucos milissegundos) e baixo consumo de memória; muito útil para casos onde sua aplicação precisa inicializar (escalar) rapidamente como em funções AWS Lambda, linhas de comando etc.;

- Estudar formas de integração com demais sistemas, principalmente nesse estágio de microsserviços: ora você precisa criar uma API (REST, síncrono), ora você precisa de algo assíncrono (mensageria). Verifique qual é a recomendação do framework escolhido, pois certamente ele terá algum tipo de suporte para uma API, seja ela REST ou GRPC. O mesmo vale para o caso de mensageria: Kafka, SQS/SNS, JMS etc.;

- Analisar a performance e características em tempo de execução da sua aplicação utilizando [JDK Flight Recorder](https://openjdk.org/jeps/328) e [JDK Mission Control](https://jdk.java.net/jmc/8/);

- Se aprofundar no mundo de testes automatizados, seja unitários com uso de mocks ([Mockito](https://site.mockito.org/) será um ótimo aliado), seja de integração com menos mocks (o que é ótimo e pode evitar muitos bugs, sendo o testcontainers o maior aliado). Testes automatizados devem ser sempre priorizados **durante** a implementação da funcionalidade, nada de deixar para depois (famoso *terminei, só falta testar*). O tempo economizado e a segurança que os testes trazem - desde que bem escritos - é de extrema importância.

- CI/CD: *continuous integration* (CI ou [integração contínua](https://pt.wikipedia.org/wiki/Integra%C3%A7%C3%A3o_cont%C3%ADnua)) e *continuous deployment* (CD ou [entrega contínua](https://pt.wikipedia.org/wiki/Entrega_cont%C3%ADnua)) são termos que você também precisará entender minimamente como funcionam. E nada melhor do que ter seus testes automatizados integrados nessas pipelines para entregar versões o mais rápido possível.


Special thanks to @gunnarmorling!