Upload
andre-justi
View
63
Download
1
Embed Size (px)
Citation preview
Grupo de EstudosSAJ-ADV
Tema: Livro Clean Code (Código Limpo) de Robert Martin Capítulos 3 e 4
Apresentado por: André Justi
Grupo de EstudosSAJ-ADV
Tema: Livro Clean Code (Código Limpo) de Robert Martin Capítulos 3 e 4
Apresentado por: André Justi
08/01/2014
Agenda
Agenda
• Capitulo 3: Funções• Capitulo 4: Comentários
Funções
Funções
“Nos primórdios da programação, formávamos nossos sistemas com rotinas e sub-rotinas. Já na era do Fortran e do PL/1, usávamos programas, subprogramas e funções. De tudo isso, apenas função prevaleceu. As funções são a primeira linha de organização em qualquer programa.”
Funções: Pequenas
Funções: Pequenas
A primeira regra para funções é que elas devem ser pequenas. A segunda é que a primeira regra nunca deve ser quebrada.Com pouca experiência podemos perceber que é muito mais fácil dar manutenção, refatorar, documentar e aplicar testes em funções pequenas.Segundo Robert Martin funções devem ter entre 1 a 5 linhas.
Funções: Blocos e endentação
Funções: Blocos e endentação
Entro de instruções como if, else, while, for e outros. Devem ter apenas uma linha. Possivelmente uma chamada de outra função. Além de manter a função pequena, isso adiciona um valor significativo, pois a função chamada de entro do bloco pode receber um nome descritivo, isso também implica que que as funções não devem ter estruturas aninhadas. Portanto, o nível de endentação de uma função deve ser de, no máximo, um ou dois níveis. Isso, é claro, facilita a leitura e compreensão da funções.
Funções: Blocos e endentação
Funções: Blocos e endentação
Exemplo ruim:
private List<String> convertePessoasJaxbParaXml(List<Pessoa> pessoas) {
List<String> pessoaXmls = new ArrayList<>();
for (Pessoa pessoa : pessoas) {
Writer writer = new StringWriter();
try {
JAXB.marshal(pessoa, writer);
pessoaXmls.add(writer.toString());
} catch (DataBindingException dataBindingException) {
throw new HttpErroAoConverterObjetoJaxbParaConteudo(dataBindingException);
} finally {
IOUtils.closeQuietly(writer);
}
}
return pessoaXmls;
Funções: Blocos e endentação
Funções: Blocos e endentação
Exemplo bom(Refatorado):
private List<String> convertePessoasJaxbParaXml(List<Pessoa> pessoas) {
List<String> pessoaXmls = new ArrayList<>();
for (Pessoa pessoa : pessoas) {
String pessoaXml = this.parsePessoaJaxbParaXml(pessoa);
pessoaXmls.add(pessoaXml);
}
return pessoaXmls;
}
Funções: Faça apenas uma coisa
Funções: Faça apenas uma coisa
As funções devem fazer apenas uma coisa e devem cumprir bem o objetivo para o qual são destinadas.O problema dessa declaração é que é difícil saber o que é “uma coisa”.
Funções: Faça apenas uma coisa
Funções: Faça apenas uma coisa
Pense no seguinte cenário: 1. Determina se a página é de teste; 2. Se for, inclui o setUps; 3. Exibe a página em HTML.
Essa descrição é uma ou são três coisas?Se uma função faz apenas uma série de passos de forma declarativa, então ela está fazendo uma só coisa. Apesar de tudo o motivo para criarmos função consiste em decompor um conceito maior (em outras palavras, o nome da função) em uma série de passos no próximo nível de abstração.
Funções: Um nível de abstração por função
Funções: Um nível de abstração por função
A fim de certificarmos que nossas funções estão fazendo "uma coisa", precisamos ter certeza de que toda lógica dentro da nossa função são todos no mesmo nível de abstração. É fácil ver como o próximo exemplo viola essa regra. Existem conceitos de lá que estão em um nível muito alto de abstração, como “converter o conteúdo dos todos objetos em uma lista de String em XML” outros que estão em um nível baixo de abstração, como: “fazer a conversão em si e tratar os possíveis erros”.
Funções: Um nível de abstração por função
Funções: Um nível de abstração por função
Misturar níveis de abstração dentro de uma função torna as coisas confusas. Quem está lendo o código não é capaz de dizer se uma determinada expressão é um conceito essencial ou um detalhe. private List<String> convertePessoasJaxbParaXml(List<Pessoa> pessoas) {
List<String> pessoaXmls = new ArrayList<>();
for (Pessoa pessoa : pessoas) {
Writer writer = new StringWriter();
try {
JAXB.marshal(pessoa, writer);
pessoaXmls.add(writer.toString());
} catch (DataBindingException dataBindingException) {
throw new HttpErroAoConverterObjetoJaxbParaConteudo(dataBindingException);
} finally {
IOUtils.closeQuietly(writer);
}
}
return pessoaXmls;
Funções: Ler o código de cima para baixo: Regra Decrescente
Funções: Ler o código de cima para baixo: Regra Decrescente
Uma função bem implementada pode ser lida de cima para baixo, como uma narrativa ou conjunto de tópicos. private List<PessoaJaxb> consultarPessoasPorNome(String nomePessoa, ParametrosConsulta parametrosConsulta) {
validarParametrosConsultas(parametrosConsulta);
List<Pessoa> pessoas = this.pessoaDao.consultarPessoasPorNome(nomePessoa, parametrosConsulta);
List<PessoaJaxb> pessoasJaxb = converterPessoasParaPessoasJaxb(pessoas);
return pessoasJaxb;
}
Funções: Use nomes descritivos
Funções: Use nomes descritivos
Não devemos ter medo de fazer uma função com nome longo. Um nome longo e descritivo é melhor do que um curto e enigmático. Um nome longo também é melhor do que um comentário longo descritivo. Seja consistente em seus nomes. Use as mesmas frases (palavras conceito/chave) em outros módulos para criar uma convenção. Isso permite que tenhamos uma de fácil dedução da função.
Funções: Parâmetros de funções
Funções: Parâmetros de funções
Sempre devemos usar um numero pequeno de parâmetros tentando não ultrapassar 3 parâmetros. Um numero menor de parâmetro também facilita o entendimento da função e testes em cima dela. Funções com muitos parâmetros exigem inúmeros testes, por existem inúmeras possibilidades.
Funções: Parâmetros lógicos
Funções: Parâmetros lógicos
Essa forma é ruim. Passar um booleano para um função certamente é uma má pratica, isso mostra explicitamente que a função faz mais de uma coisa. Normalmente uma se o parâmetro for verdadeiro e outra se o parâmetro for falso.
Funções: Evite efeitos colaterais
Funções: Evite efeitos colaterais
Os efeitos colaterais são mentiras. Sua função promete fazer uma coisa, mas ele também faz outra. Às vezes ele vai fazer mudanças inesperadas em variáveis ??da própria classe.Às vezes ele vai fazer mudanças inesperadas em parâmetros passados na função ou parâmetros globais da aplicação.Em ambos os casos elas são "verdades" enganosas e prejudiciais, que geralmente resultam em comportamentos estranhos.
Funções: Separação comando/consulta
Funções: Separação comando/consulta
As funções devem fazer ou responder algo, mas não ambos. Sua função ou altera o estado de um objeto ou retorna informações sobre ele. Efetuar as duas tarefas costuma gerar confusão.
Funções: Evite repetição
Funções: Evite repetição
Evite sempre a repetição. Sempre que uma função ou parte se repetir, torne elas comuns ou extraia apenas o bloco repetido para outra função comum.
Comentários
Comentários
“Não insira cometários em um código ruim, reescreva-o”.- Brian W. Kernighan
Nada pode ser tão útil quanto um comentário bem colocado, nada consegue ser tão prejudicial quanto um velho comentário mal feito e que fala mentiras e informações incorretas.
Comentários: Comentários compensam um código ruim
Comentários: Comentários compensam um código ruim
Uma das motivações mais comuns para criar cometários é um código ruim, construímos um módulo e sabemos que está confuso e desorganizado. Estamos cientes da bagunça. Nós mesmos dizemos “Oh é melhor inserir um comentário!”. Não... acredite é melhor para e limpar a bagunça.
Comentários: Explique-se no código
Comentários: Explique-se no código
Certamente há vezes em que não é possível expressar-se direto no código. Infelizmente, devido a isso, muitos desenvolvedores assumiram que o código raramente é, se é que possa ser, um bom meio para se explicar. Evidentemente isso é falso.
Comentários: Explique-se no código
Comentários: Explique-se no código
Oque você preferiria ver?
private void editarPessoa(Pessoa pessoa) {
if (pessoa == null
|| pessoa.getCodigo() == null
|| pessoa.getCodigo() < 1
|| this.pessoaDao.pessoaExiste(pessoa.getCodigo())) {
//Lança erro informando que pessoa não existe.
}
this.pessoaDao.salvarPessoa(pessoa);
}
Comentários: Explique-se no código
Comentários: Explique-se no código
Ou isso?
private void editarPessoa(Pessoa pessoa) {
if (this.verificaExistenciaPessoa(pessoa)) {
//Lança erro informando que pessoa não existe.
}
this.pessoaDao.salvarPessoa(pessoa);
}
private boolean verificaExistenciaPessoa(Pessoa pessoa) {
if (pessoa == null) {
return false;
}
Long codigoPessoa = pessoa.getCodigo();
if (pessoa.getCodigo() == null || pessoa.getCodigo() < 1) {
return false;
}
return this.pessoaDao.pessoaExiste(pessoa.getCodigo());
}
Comentários: Comentários informativos
Comentários: Comentários informativos
Às vezes é pratico fornecer informações básicas em um comentário. /** Regex para identificação do parâmetro 'import' da tag page com case insensitive. */
private static final String REGEX_PARAMETER_IMPORT = "(?i)import=[\"'].+?([\"'])";
Comentários: Alerta sobre consequências
Comentários: Alerta sobre consequências
Às vezes é útil alertar outros desenvolvedores sobre certas consequências. Por exemplo. o comentário abaixo explica porque um caso de teste em particular está desabilitado.
Mesmos assim sempre existem outras possibilidades.
// Teste está comentado porque demorar muito para ser testado, só execute se tiver tempo.
//
// @Test
// public void verificaPessoasCpfInvalidoTest() {
// //Implementação
// }
@Test
@Ignore("Só execute se tiver tempo")
public void verificaPessoasCpfInvalidoTest() {
//Implementação
}
Comentários: Comentários TODO
Comentários: Comentários TODO
Às vezes é cabível deixar notas “TODO” em comentários. TODO explica por que a função tem uma implementação degradante ou um ponte de revisão. Vale lembrar que existem outras formas de prever isso como ferramentas de revisão de código.
Comentários: Javadocs em APIs públicas
Comentários: Javadocs em APIs públicas
Não há nada tão prático e satisfatório como uma API pública bem descrita. Os Javados para a biblioteca Java padrão são um exemplo. Mesmo com um código ruim é possível usar seus artefatos.
Comentários: Comentários ruins
Comentários: Comentários ruins
A maioria dos comentários está nessa categoria. Geralmente eles são suportes ou desculpas para um código de baixa qualidade ou justificativa para a falta de decisões.
Comentários: Comentários enganadores
Comentários: Comentários enganadores
Às vezes, com as melhores intenções, um desenvolvedor faz uma afirmação não muito clara em seus comentários. Lembre-se: se vai escrevê-los, invista tempo e escreva-os bem.
Comentários: Comentários imperativos
Comentários: Comentários imperativos
É basicamente tolo ter uma regra dizendo que todo artefato deve ter um Javadoc. Isso muitas vezes é redundante, torna o código mais complexo e desorganizado e muitas vezes aumenta em muito o custo do desenvolvimento.
Comentários: Comentários ruidosos
Comentários: Comentários ruidosos
Às vezes você vê comentários que nada são além de “chiados”. Eles dizem o óbvio./**
* Recupera o código da pessoa.
*
* @return Código da pessoa.
*/
public Long getCodigoPessoa(){
this.codigoPessoa;
}
Comentários: Evite comentários se é possível usar uma função ou uma variável
Comentários: Evite comentários se é possível usar uma função ou uma variável
Às vezes podemos usar funções ou variáveis bem nomeadas ao invés de comentários.
Oque você preferiria ver?private void editarPessoa(Pessoa pessoa) {
//Verifica se pessoa existe
if (pessoa.getCodigo() == null
|| pessoa.getCodigo() < 1
|| this.pessoaDao.pessoaExiste(pessoa.getCodigo())) {
//Lança erro informando que pessoa não existe.
}
this.pessoaDao.salvarPessoa(pessoa);
}
Comentários: Evite comentários se é possível usar uma função ou uma variável
Comentários: Evite comentários se é possível usar uma função ou uma variável
Ou isso?
private void editarPessoa(Pessoa pessoa) {
if (this.verificaExistenciaPessoa(pessoa)) {
//Lança erro informando que pessoa não existe.
}
this.pessoaDao.salvarPessoa(pessoa);
}
Comentários: Créditos e autoria
Comentários: Créditos e autoria
Os sistemas de controle e versionamento de código são muito bons para lembrar quem alterou ou adicionou algo ao código. Não há necessidade de poluir o código com isso.
/* Adicionar por André Justi */
Comentários: E agora?
Comentários: E agora?
Aonde devemos usar comentários e Javadocs?