Padrões de Projeto, Arquiteturas, Testes, Banco de Dados e Boas Práticas
1. Outros Padrões de Projeto
Os padrões de projeto são soluções reutilizáveis para problemas recorrentes no desenvolvimento de software. Eles ajudam a estruturar o código de maneira eficiente e facilitam a manutenção e escalabilidade do sistema.
1.1 Factory Method
-
Define uma interface para criação de objetos, mas permite que subclasses alterem o tipo de objetos criados.
-
Útil quando a criação de um objeto envolve lógica complexa ou quando não queremos expor diretamente a instância da classe.
-
Exemplo:
interface Produto {
void criar();
}
class ProdutoA implements Produto {
public void criar() {
System.out.println("Produto A criado");
}
}
class FabricaDeProdutos {
public static Produto criarProduto(String tipo) {
if (tipo.equals("A")) {
return new ProdutoA();
}
throw new IllegalArgumentException("Tipo desconhecido");
}
}
1.2 Singleton
-
Garante que uma classe tenha apenas uma instância e fornece um ponto global de acesso a ela.
-
Usado para gerenciar recursos compartilhados, como conexões de banco de dados.
-
Exemplo:
public class Configuracao {
private static Configuracao instancia;
private Configuracao() {}
public static Configuracao getInstance() {
if (instancia == null) {
instancia = new Configuracao();
}
return instancia;
}
}
1.3 Observer
-
Define uma dependência um-para-muitos entre objetos, onde um objeto (sujeito) notifica múltiplos observadores sobre mudanças de estado.
-
Muito utilizado em eventos e sistemas de notificação.
-
Exemplo:
interface Observador {
void atualizar(String mensagem);
}
class Usuario implements Observador {
private String nome;
public Usuario(String nome) { this.nome = nome; }
public void atualizar(String mensagem) {
System.out.println(nome + " recebeu: " + mensagem);
}
}
class Notificador {
private List<Observador> observadores = new ArrayList<>();
public void adicionar(Observador o) { observadores.add(o); }
public void notificarTodos(String mensagem) {
for (Observador o : observadores) {
o.atualizar(mensagem);
}
}
}
1.4 Decorator
-
Permite adicionar funcionalidades a objetos dinamicamente sem modificar suas classes.
-
Exemplo:
interface Cafe {
String descricao();
}
class CafeSimples implements Cafe {
public String descricao() { return "Café Simples"; }
}
class LeiteDecorator implements Cafe {
private Cafe cafe;
public LeiteDecorator(Cafe cafe) { this.cafe = cafe; }
public String descricao() { return cafe.descricao() + ", com leite"; }
}
1.5 Adapter
-
Converte a interface de uma classe em outra interface esperada pelos clientes.
-
Útil para integrar sistemas legados com novas APIs.
-
Exemplo:
class TomadaAntiga {
public void ligarNaTomadaDoisPinos() {
System.out.println("Ligado na tomada de dois pinos");
}
}
class AdaptadorTomada {
private TomadaAntiga tomada;
public AdaptadorTomada(TomadaAntiga tomada) { this.tomada = tomada; }
public void ligarNaTomadaTresPinos() {
tomada.ligarNaTomadaDoisPinos();
}
}
2. Arquiteturas
Diferentes arquiteturas são usadas para estruturar aplicações de forma escalável e organizada.
2.1 Microservices vs Monólito
- Monólito: Aplicação única e indivisível.
- Microservices: Divisão da aplicação em serviços independentes e interoperáveis.
- Vantagens dos microservices: escalabilidade, deploy independente.
- Vantagens do monólito: menor complexidade inicial, mais fácil de testar.
2.2 DDD (Domain-Driven Design)
- Modela o software com base na lógica do domínio de negócio.
- Utiliza conceitos como Entidades, Agregados, Repositorios e Serviços de Domínio.
- Focado em colaboração com especialistas do domínio.
2.3 Arquitetura Hexagonal
- Separa a lógica de negócios da infraestrutura (banco de dados, frameworks, interfaces gráficas).
- Utiliza portas e adaptadores para desacoplar dependências externas.
- Facilita testes e manutenibilidade.
3. Testes e Qualidade
Os testes garantem a confiabilidade e robustez do código.
3.1 JUnit
- Framework para testes unitários em Java.
- Exemplo de teste:
@Test
public void testSoma() {
assertEquals(4, Calculadora.somar(2, 2));
}
3.2 Mockito
- Framework para simulação (mocking) de objetos.
- Exemplo:
Mockito.when(repositorio.buscarPorId(1L)).thenReturn(new Cliente("João"));
3.3 Testes de Integração no Spring
- Testes que validam a integração entre diferentes partes do sistema.
- Utilizam o Spring Boot Test para configurar um ambiente de testes realista.
- Exemplo:
@SpringBootTest
public class ClienteServiceTest {
@Autowired
private ClienteService clienteService;
@Test
public void testBuscarCliente() {
Cliente cliente = clienteService.buscarPorId(1L);
assertNotNull(cliente);
}
}
4. Banco de Dados
Os bancos de dados armazenam e gerenciam dados da aplicação.
4.1 JDBC
- API para interação direta com bancos de dados SQL.
- Exemplo de conexão:
Connection conn = DriverManager.getConnection(url, user, password);
4.2 JPA/Hibernate
- JPA: Especificação Java para persistência de dados.
- Hibernate: Implementação da JPA.
- Exemplo de entidade:
@Entity
public class Usuario {
@Id
@GeneratedValue
private Long id;
private String nome;
}
4.3 NoSQL
- Bancos de dados não relacionais (MongoDB, Redis, Cassandra).
- Utilizados para alta escalabilidade e flexibilidade de estrutura de dados.
5. Boas Práticas
5.1 Clean Code
- Código limpo e de fácil entendimento.
- Princípios: nomes significativos, funções pequenas, evitar repetições.
5.2 DRY (Don’t Repeat Yourself)
- Evitar duplicação de código.
- Exemplo: Criar métodos reutilizáveis em vez de copiar e colar código.
5.3 KISS (Keep It Simple, Stupid)
- Manter o código simples e direto.
- Evitar complexidade desnecessária.
5.4 YAGNI (You Aren’t Gonna Need It)
- Implementar apenas o que é necessário.
- Evitar adicionar funcionalidades prematuramente.
6. Assuntos Complementares
6.1 Design Patterns Avançados
- Padrões como Strategy, Prototype, Mediator, Chain of Responsibility.
- Comparação: Strategy permite troca de algoritmos dinamicamente, enquanto Singleton restringe instância única.
6.2 CI/CD (Integração Contínua e Entrega Contínua)
- Ferramentas: Jenkins, GitHub Actions, GitLab CI.
- Comparação: Jenkins é altamente configurável, enquanto GitHub Actions é integrado ao GitHub.
6.3 Cloud Computing
- AWS, Azure, Google Cloud.
- Comparação: AWS tem mais serviços, enquanto Google Cloud é forte em IA/ML.
6.4 Segurança em Aplicações
- Princípios de segurança: OWASP, JWT, OAuth.
- Comparação: JWT é usado para autenticação stateless, enquanto OAuth é mais amplo para autorização.
6.5 Performance e Escalabilidade
- Caching (Redis), Load Balancers, Otimização de Queries.
- Comparação: Redis é um cache na memória, enquanto Load Balancer distribui requisições.
Conclusão
Este guia fornece uma visão geral de padrões de projeto, arquiteturas, testes, banco de dados e boas práticas essenciais para desenvolvimento de software. Além disso, explorar tópicos complementares ajudará o estudante a aprofundar seus conhecimentos e desenvolver sistemas robustos e escaláveis.