36
Grupo de Estudos SAJ-ADV Tema: Livro Clean Code (Código Limpo) de Robert Martin Capítulos 3 e 4 Apresentado por: André Justi Grupo de Estudos SAJ-ADV Tema: Livro Clean Code (Código Limpo) de Robert Martin Capítulos 3 e 4 Apresentado por: André Justi 08/01/2014

Livro - código limpo caps (3,4) (clean code)

Embed Size (px)

Citation preview

Page 1: Livro - código limpo caps (3,4) (clean code)

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

Page 2: Livro - código limpo caps (3,4) (clean code)

Agenda

Agenda

• Capitulo 3: Funções• Capitulo 4: Comentários

Page 3: Livro - código limpo caps (3,4) (clean code)

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.”

Page 4: Livro - código limpo caps (3,4) (clean code)

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.

Page 5: Livro - código limpo caps (3,4) (clean code)

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.

Page 6: Livro - código limpo caps (3,4) (clean code)

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;

Page 7: Livro - código limpo caps (3,4) (clean code)

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;

}

Page 8: Livro - código limpo caps (3,4) (clean code)

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”.

Page 9: Livro - código limpo caps (3,4) (clean code)

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.

Page 10: Livro - código limpo caps (3,4) (clean code)

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”.

Page 11: Livro - código limpo caps (3,4) (clean code)

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;

Page 12: Livro - código limpo caps (3,4) (clean code)

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;

}

Page 13: Livro - código limpo caps (3,4) (clean code)

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.

Page 14: Livro - código limpo caps (3,4) (clean code)

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.

Page 15: Livro - código limpo caps (3,4) (clean code)

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.

Page 16: Livro - código limpo caps (3,4) (clean code)

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.

Page 17: Livro - código limpo caps (3,4) (clean code)

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.

Page 18: Livro - código limpo caps (3,4) (clean code)

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.

Page 19: Livro - código limpo caps (3,4) (clean code)

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.

Page 20: Livro - código limpo caps (3,4) (clean code)

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.

Page 21: Livro - código limpo caps (3,4) (clean code)

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.

Page 22: Livro - código limpo caps (3,4) (clean code)

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);

}

Page 23: Livro - código limpo caps (3,4) (clean code)

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());

}

Page 24: Livro - código limpo caps (3,4) (clean code)

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=[\"'].+?([\"'])";

Page 25: Livro - código limpo caps (3,4) (clean code)

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

}

Page 26: Livro - código limpo caps (3,4) (clean code)

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.

Page 27: Livro - código limpo caps (3,4) (clean code)

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.

Page 28: Livro - código limpo caps (3,4) (clean code)

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.

Page 29: Livro - código limpo caps (3,4) (clean code)

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.

Page 30: Livro - código limpo caps (3,4) (clean code)

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.

Page 31: Livro - código limpo caps (3,4) (clean code)

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;

}

Page 32: Livro - código limpo caps (3,4) (clean code)

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);

}

Page 33: Livro - código limpo caps (3,4) (clean code)

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);

}

Page 34: Livro - código limpo caps (3,4) (clean code)

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 */

Page 35: Livro - código limpo caps (3,4) (clean code)

Comentários: E agora?

Comentários: E agora?

Aonde devemos usar comentários e Javadocs?

Page 36: Livro - código limpo caps (3,4) (clean code)