O documento descreve princípios de projeto de software como SRP, OCP, LSP, ISP e DIP. Também apresenta padrões de projeto como Strategy e State. Strategy separa algoritmos em classes distintas para permitir troca de comportamento em tempo de execução. State permite que um objeto altere seu comportamento com base em seu estado interno.
4. public class CalculadoraDeSalario
(m) double calcula(Funcionario)
public class Funcionario
// mais campos
(f) Cargo cargo;
(f) double salarioBase;
(m) double calculaSalario;
public enum Cargo {
DESENVOLVEDOR(new DezOuVintePorCento()),
DBA(new QuinzeOuVinteCincoPorCento()),
TESTER(new QuinzeOuVinteCincoPorCento());
(f) RegraDeCalculo regra;
(c) Cargo(RegraDeCalculo regra) this.regra = regra;
(m) RegraDeCalculo getRegra
public interface RegraDeCalculo
(m) double calcula(Funcionario)
public double calculaSalario() {
return cargo.getRegra().calcula(this);
}
5. OCP - Open/Closed Principle
- Aberta para extensão
- Fechada para modificação
6. LSP - Liskov Substitutive Principle
- Classes derivadas devem ser substituíveis por suas
classes bases
- Deve-se pensar muito nas pré-condições e pós-condições
7. ISP - Interface Segregation Principle
- Clientes não devem ser forçados a depender de métodos
que não usam
8. DIP - Dependency Inversion Principle
- Dependa sempre de abstração, não de implementação
9. Don’t repeat yourself - Não repetir código, movendo partes
que precisam ser reutilizadas para métodos ou classes.
WET -
“Write Everything Twice”
“We Enjoy Typing”
“Waste Everyone’s Time”
DRY
11. private static String semana(int dia) {
switch (dia){
case 1:
return "Segunda-feira";
case 2:
return "Terça-feira";
case 3:
return "Quarta-feira";
case 4:
return "Quinta-feira";
case 5:
return "Sexta-feira";
case 6:
return "Sabado";
case 7:
return "Domingo";
default:
throw new IllegalArgumentException("Dia
inválido: Somente números entre 1 e 7");
}
}
private static String semana(int dia) {
if(dia < 1 || dia > 7) throw new
IllegalArgumentException("Dia inválido: Somente
números entre 1 e 7");
String[] diasDaSemana = {
"Segunda-feira",
"Terça-feira",
"Quarta-feira",
"Quinta-feira",
"Sexta-feira",
"Sábado",
"Domingo"
};
return diasDaSemana[dia - 1];
}
12. API Best Practices
1) HTTP aplicado a REST
- Conhecer bem a base
2) Não retorne texto puro
- Passar o content-type!
13. 3) Evite usar verbos nas URIs
- Metodos HTTP devem ser suficiente para
descrever a ação
4) Use plurais nos recursos
- É preferível o uso de plurais para garantir a
padronização
GET /loja/listaClientes/
GET /loja/clientes/
GET /loja/cliente/1
GET /loja/clientes/
GET /loja/clientes/
POST /loja/clientes/
14. 5) Retorne detalhes dos erros no body
- Retornar detalhes de erros ajuda a fazer o
debug
6) Retorne StatusCodes significativos
{
“error” : “Email inválido”
“detail” : {
“surname” :
“...”
}
}
HTTP/1.1 200 OK
Content-Type: text/html
{
"status": "failure",
"data": {
"error": "Nome é obrigatório"
}
}
15. 7) Use StatusCode consistentemente
- Use um padrão
- Retorne sempre o mesmo StatusCode para
aquele tipo de requisição
8) Evite Nested Resources
- Pode ficar confuso
- Prefira QueryParams
GET /pacientes/5/prontuario
GET /prontuarios/?paciente_id=5
16. 9) Lide com barras finais 10) Use QueryParams para filtros e paginação
POST /pacientes
POST /pacientes/
GET /artigos/?page=8&size=10
GET /artigos/revisados
GET /artigos/?revisados=true&page=5&size=10
17. Style Guide - Java
Um conjunto de regras para padronizar a escrita do código,
regendo desde a identação do código até a criação do Javadoc
18. Algumas regras
Segundo o Google JavaStryleGuide: https://google.github.io/styleguide/javaguide.html
- Estrutura do arquivo-fonte;
- Caracteres especiais
- Formatação;
- Nomenclatura;
20. Strategy
- Separa os algoritmos para alcançar a reusabilidade
- Permite selecionar um algoritmo durante a execução
Contexto
<<interface>>
Estratégia
+executa()
Estratégia
1
+executa()
Estratégia
2
+executa()
21. public class CalculadoraDeImpostos {
public void realizaCalculo(Orcamento orcamento, String imposto) {
if(imposto.equals("ICMS")) System.out.println(orcamento.getValor() * 0.1);
else if (imposto.equals("ISS")) System.out.println(orcamento.getValor() * 0.06);
// else if mais um
// else if e outro
// else if continua crescendo
// else if não para
}
}
22. public class CalculadoraDeImpostos {
public void realizaCalculoICMS(Orcamento orcamento) {
System.out.println(new ICMS().calculaICMS(orcamento));
}
public void realizaCalculoISS(Orcamento orcamento) {
System.out.println(new ISS().calculaISS(orcamento));
}
// E mais um método
// E outro
// E aqui mais um
}
23. public class CalculadoraDeImpostos {
public void realizaCalculo(Orcamento orcamento, Imposto
imposto) {
System.out.println(imposto.calcula(orcamento));
}
}
public interface Imposto {
double calcula(Orcamento orcamento);
}
public class ICMS implements Imposto {
@Override
public double calcula(Orcamento orcamento) {
return orcamento.getValor() * 0.1;
}
}
public class ISS implements Imposto {
@Override
public double calcula(Orcamento orcamento) {
return orcamento.getValor() * 0.06;
}
}
public class TesteCalculadora {
public static void main(String[] args) {
Orcamento orcamento = new Orcamento(500);
var calculadora = new CalculadoraDeImpostos();
System.out.println("******* ICMS *********");
calculadora.realizaCalculo(orcamento, new ICMS());
System.out.println("******* ISS *********");
calculadora.realizaCalculo(orcamento, new ISS());
}
}
24. State
- Permite alterar o comportamento baseado no estado interno do objeto
<<interface>>
Estado
+acao1()
+ação2()
Estado 1
+acao1()
+acao2()
Estado 2
+acao1()
+acao2()
Contexto
+metodo()
estado;
25. public class Orcamento {
private double valor;
private List<Item> itens;
public Orcamento(double valor) {
this.valor = valor;
this.itens = new ArrayList<Item>();
}
public double getValor() { return valor; }
public void desconta(double valor) {
this.valor -= valor;
}
public List<Item> getItens() {
return Collections.unmodifiableList(itens);
}
public void adicionaItem(Item item) {
itens.add(item);
}
}
public class Orcamento {
public static final int EM_APROVACAO = 1;
public static final int APROVADO = 2;
public static final int REPROVADO = 3;
public static final int FINALIZADO = 4;
private double valor;
private List<Item> itens;
private int estadoAtual;
// resto da classe escondida porque não cabia mais na tela
public void aplicaDescontoExtra() {
if(estadoAtual == EM_APROVACAO) valor = valor - (valor * 0.05);
else if(estadoAtual == APROVADO) valor = valor - (valor * 0.02);
else throw new RuntimeException("Orçamentos reprovados não
recebem desconto extra!");
}
}
26. public class Orcamento {
private double valor;
private List<Item> itens;
private EstadoAtualDeUmOrcamento estadoAtual;
public Orcamento(double valor) {
this.valor = valor;
this.itens = new ArrayList<Item>();
this.estadoAtual = new EmAprovacao();
}
// resto da classe porque não cabia mais na tela
public void aplicaDescontoExtra() {
estadoAtual.aplicaDescontoExtra(this);
}
}
Em Aprovação
Aprovado Reprovado
Finalizado
27. public class Orcamento {
// resto da classe porque não cabia mais na tela
public void
alteraEstado(EstadoAtualDeUmOrcamento
novoEstado) {
this.estadoAtual = novoEstado;
}
public void aprova() {
estadoAtual.aprova(this);
}
public void reprova() {
estadoAtual.reprova(this);
}
public void finaliza() {
estadoAtual.finaliza(this);
}
}
public interface EstadoAtualDeUmOrcamento {
void aplicaDescontoExtra(Orcamento orcamento);
void aprova(Orcamento orcamento);
void reprova(Orcamento orcamento);
void finaliza(Orcamento orcamento);
}
public class EmAprovacao implements EstadoAtualDeUmOrcamento {
@Override
public void aplicaDescontoExtra(Orcamento orcamento) {
orcamento.desconta(orcamento.getValor() * 0.05); }
@Override
public void aprova(Orcamento orcamento) {
orcamento.alteraEstado(new Aprovado()); }
@Override
public void reprova(Orcamento orcamento) {
orcamento.alteraEstado(new Reprovado());}
@Override
public void finaliza(Orcamento orcamento) {
throw new IllegalStateException("Orçamentos em aprovação não
podem ser finalizados"); }
}