Etapa 0: Configuração e Versionamento
Objetivos
- Configurar o ambiente de desenvolvimento Java (JDK) e Ferramenta de Build (Maven).
- Estabelecer o fluxo de trabalho colaborativo via Git.
- Garantir que todos conseguem compilar e executar um código Java básico.
Pré-requisitos
- Java JDK 21+: Download OpenJDK ou instalar via gerenciador de pacotes.
- Maven: Download Apache Maven.
- Git: Download Git.
- IDE Sugerida: IntelliJ IDEA (Community ou Ultimate) ou VS Code com Extension Pack for Java.
Atividades Práticas
1. Repositório
- O trabalho será individual.
- Criar um repositório privado no GitLab do Prof. Alessio: https://git.juninho.com.br/.
- Adicionar o professor como membro do projeto (
MaintainerouDeveloper). - Regra de Equilíbrio: O histórico de commits deve mostrar participação balanceada do aluno.
2. Inicializando o Projeto (Hello World)
Vamos criar a estrutura básica (“esqueleto”) do compilador usando o Maven. Abra o terminal na pasta onde deseja salvar o projeto:
mvn archetype:generate \
-DgroupId=br.com.comcet \
-DartifactId=comcet \
-Dpackage=br.com.comcet.tp0 \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DinteractiveMode=falseIsso criará uma pasta comcet. Entre nela:
cd comcet3. Configurando o pom.xml
Abra o arquivo pom.xml e certifique-se de que a versão do compilador Java está correta (mude de 1.7/1.8 para 21):
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.1</version>
<scope>test</scope>
</dependency>
</dependencies>4. Desenvolvendo o Código Inicial (Leitura de Arquivo)
Como o primeiro passo de um compilador é ler o arquivo fonte, vamos garantir que seu ambiente Java sabe ler arquivos e usar estruturas de repetição básicas, indo além de um simples “Hello World”.
Navegue até src/main/java/br/com/comcet/tp0/App.java e implemente o ponto de entrada principal. O programa deve priorizar argumentos de linha de comando (args), suportar a flag -f para arquivos, e entrar em modo interativo caso nenhum argumento seja fornecido.
package br.com.comcet.tp0;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.*;
import java.util.stream.Collectors;
public class App {
public static void main(String[] args) {
String input = "";
boolean isFilePath = false;
// 1. Prioridade: Argumentos de Linha de Comando (CLI)
if (args.length > 0) {
if (args[0].equals("-f") && args.length > 1) {
input = args[1];
isFilePath = true;
} else {
input = args[0];
// Detecção automática simples se não houver flag
if (input.toLowerCase().endsWith(".txt") && new File(input).exists()) {
isFilePath = true;
}
}
}
// 2. Fallback: Entrada Interativa (Scanner)
else {
Scanner keyboard = new Scanner(System.in);
System.out.print("Digite o texto ou o caminho de um arquivo .txt: ");
input = keyboard.nextLine();
if (input.toLowerCase().endsWith(".txt") && new File(input).exists()) {
isFilePath = true;
}
keyboard.close();
}
String content = "";
if (isFilePath) {
try {
content = new Scanner(new File(input)).useDelimiter("\\Z").next();
} catch (FileNotFoundException e) {
System.err.println("Erro: Arquivo não encontrado: " + input);
return;
}
} else {
content = input;
}
exibirEstatisticas(content);
}
public static void exibirEstatisticas(String text) {
// TODO: Implementar a lógica de estatísticas aqui
// 1. Limpar o texto (remover pontuação, converter para minúsculas)
// 2. Contar caracteres (apenas letras a-zA-Z) -> "Caracteres: X"
// 3. Contar total de palavras -> "Palavras: X"
// 4. Encontrar letra mais frequente -> "Frequente: X"
// (Critério: presente em mais palavras diferentes. Desempate: Alfabético A-Z)
// 5. Encontrar palavra mais frequente -> "Frequente: X"
// (Desempate: Alfabético A-Z)
System.out.println("LOGICA A SER IMPLEMENTADA");
}
}Sua tarefa é implementar o método exibirEstatisticas para que ele produza exatamente a saída esperada nos exemplos abaixo. Atente-se aos rótulos e aos critérios de desempate alfabético.
Crie um arquivo teste.txt com um parágrafo longo para testar, ou passe uma frase entre aspas.
Compile e execute:
mvn package
# Modo Interativo (sem argumentos)
java -cp target/comcet-1.0-SNAPSHOT.jar br.com.comcet.tp0.App
# Modo Direto (passando string)
java -cp target/comcet-1.0-SNAPSHOT.jar br.com.comcet.tp0.App "Texto de teste"
# Modo Arquivo (usando flag)
java -cp target/comcet-1.0-SNAPSHOT.jar br.com.comcet.tp0.App -f teste.txtExemplos de Entrada e Saída
| Entrada (IN) | Saída Esperada (OUT) |
|---|---|
Texto Direto:"Compiladores sao divertidos" |
Caracteres: 25Frequente: oPalavras: 3Frequente: compiladores |
Arquivo exemplo.txt:-f exemplo.txt(Conteúdo: O rato roeu a roupa do rei.) |
Caracteres: 20Frequente: oPalavras: 7Frequente: a |
Se aparecer a mensagem de Sucesso com a contagem de palavras, parabéns! Seu ambiente e suas rotinas de leitura de arquivo estão prontos.
5. Garantindo a Qualidade (Testes Unitários)
Um compilador é um software crítico. Para garantir que pequenas mudanças não quebrem funcionalidades antigas, usaremos testes automatizados.
Crie o arquivo src/test/java/br/com/comcet/tp0/AppTest.java para validar as lógicas de limpeza e estatísticas:
package br.com.comcet.tp0;
import org.junit.jupiter.api.Test;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class AppTest {
@Test
public void testEstatisticasBasicas() {
ByteArrayOutputStream outContent = new ByteArrayOutputStream();
System.setOut(new PrintStream(outContent));
App.exibirEstatisticas("Java e legal. Java e potente.");
String output = outContent.toString();
assertTrue(output.contains("Caracteres: 22"));
assertTrue(output.contains("Palavras: 6"));
assertTrue(output.contains("Frequente: e")); // Letra e palavra 'e'
}
@Test
public void testTextoDireto() {
ByteArrayOutputStream outContent = new ByteArrayOutputStream();
System.setOut(new PrintStream(outContent));
App.exibirEstatisticas("Compiladores sao divertidos");
String output = outContent.toString();
assertTrue(output.contains("Caracteres: 25"));
assertTrue(output.contains("Frequente: o"));
assertTrue(output.contains("Palavras: 3"));
assertTrue(output.contains("Frequente: compiladores"));
}
@Test
public void testTextoVazio() {
ByteArrayOutputStream outContent = new ByteArrayOutputStream();
System.setOut(new PrintStream(outContent));
App.exibirEstatisticas("");
String output = outContent.toString();
assertTrue(output.contains("Texto vazio."));
}
}Execute os testes:
mvn test6. Automação com CI/CD (GitLab)
Para que o professor consiga validar seu trabalho e para que você tenha certeza de que seu código compila em qualquer lugar, vamos configurar um Pipeline de Integração Contínua (CI).
Crie um arquivo chamado .gitlab-ci.yml na raiz do seu projeto:
image: maven:3.9.6-eclipse-temurin-21
stages:
- build
- test
build_job:
stage: build
script:
- mvn compile
test_job:
stage: test
script:
- mvn testToda vez que você der um git push, o GitLab executará esses passos automaticamente!
7. Versionando
Agora, suba esse código inicial para o seu repositório Git.
Crie um arquivo
.gitignorena raiz do projeto (para não enviar a pastatarget):target/ .idea/ .vscode/ *.classInicialize e envie:
git init git add . git commit -m "Estrutura inicial do projeto com Maven" git remote add origin <URL_DO_SEU_REPO_GITLAB> git push -u origin main
8. Verificando o Pipeline
Após o push, vá até o menu Build > Pipelines no seu repositório no GitLab e verifique se o seu código passou nos testes automatizados.
Critérios de Sucesso
- Repositório criado e compartilhado com o professor.
- Código Java priorizando
args[]e aceitando flag-f. - Suporte a
Scanner(System.in)caso nenhum argumento seja fornecido. - Relatório Completo de estatísticas como no exemplo.
- Testes Unitários passando localmente (
mvn test). - Pipeline de CI/CD no GitLab com status “Passed”.