SlideShare a Scribd company logo
1 of 60
Download to read offline
Código Limpo
     Capítulo 3 - Funções




 Bruno Blumenschein
 Hélios Kárum de Oliveira Bastos
 Rodrigo Oliveira Andrade
Regras
● Primeira Regra:
  ○ As funções devem ser pequenas;
● Segunda Regra:
  ○ "Elas precisam ser ainda menores";
● Não há como provar porque, foi baseado
  nas tentativas e erros do autor.
● Não ultrapassar mais do que 20 linhas, com
  150 carcteres por linha.
Exemplo
Exemplo - Continuação
Exemplo - Primeira Melhoria
Exemplo - Segunda Melhoria
Blocos e Identação
● Seguindo a linha de se minimizar funções,
  instruções como if, else e while devem
  possuir apenas uma linha de código.
● E provavelmente esta linha será uma
  chamada a uma função.
● Além de manter a função pequena agrega
  valor de documentação, já que o nome da
  função deve ser bem descritivo.
Blocos e Identação
● Essa estrutura também implica que as
  funções não devem ter muitas estruturas
  aninhadas.
● Para facilitar a estrutura e identação o
  nível máximo de estruturas aninhadas deve
  ser de uma ou duas.
Fazer apenas uma Coisa
● "Functions should do one thing. They should
  do it well. The should do it only."
● Funções devem fazer uma única coisa. Elas
  devem fazê-la bem. Elas devem fazer
  apenas ela.
● O problema é saber o que é "uma única
  coisa".
Fazer apenas uma Coisa
● O que faz o programa do exemplo anterior
   (RenderPageWithSetupsAndTeardowns):
  1. Determina se a página é de teste;
  2. Se for, inclui setUps e tearDowns;
  3. Renderiza a página em HTML.
● É apenas uma função ou são três?
● Note que as três operações realizadas estão
   a um nível abaixo do nome da função.
● Então ela está fazendo uma coisa só.
Fazer apenas uma Coisa
● O motivo de criarmos uma função é para
  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.
Seções em Funções
● Funções que fazem apenas apenas uma
  coisa não podem ser razoavelmente
  divididas em seções.
● Caso isto aconteça é um sintoma de estar
  fazendo mais de uma coisa.
Um Nível de Abstração por Função
● A fim de confirmar se uma função só faz
  uma coisa, precisamos verificar se todas as
  intruções dentro da função estão no mesmo
  nível de abstração.
● Vários níveis de abstração dentro de uma
  função sempre geram confusão.
● Os leitores podem não conseguir dizer se
  uma expressão determinada é um conceito
  essêncial ou um mero detalhe.
Ler o Código de Cima para Baixo
● O código deve ser lido de maneira top-
  down.
● Desejamos que cada função seja seguida
  pelas outras no próximo nível de abstração,
  de modo que possamos ler o programa um
  nível de cada vez.
● Chamamos isso de regra descendente.
Exemplo
● Para incluir setups e teardowns, nós incluimos
  primeiro os setups, depois nós incluimos o
  conteúdo da página de testes, e então incluimos
  os teardowns;
● Para incluir os setups, nós incluimos o suite
  setup se for uma suite, e então incluimos o setup
  regular;
● Para incluir o suite setup, nós procuramos na
  hierarquia pela página "SuiteSetUp", e então
  adicionamos uma instrução com o caminho para
  aquela página.
● Para procurar a hierarquia a cima...
Ler o Código de Cima para Baixo
● Acaba sendo difícil para o programador
  aplicar essa regra, mas quando ele passa a
  dominar esse truque, ele passa a ter o
  controle de verificação para saber se uma
  função só faz apenas uma coisa.
Switch
● É difícil criarmos um swtich pequeno.
● Mesmo o menor switch possível, com dois
  casos, já é maior do que eu gostaria de ter
  em um único bloco de código.
● É difícil criar um switch que faça apenas
  uma coisa.
● Pela sua natureza eles são criados para
  fazerem N coisas.
● Infelizemente nós não podemos evitar o uso
  de switchs.
Switch
● Mas nós podemos nos assegurar que cada
  instrução está um nível de abstração abaixo
  e que nunca se repetem.
● Switch geralmente tem vários problemas
  com o Principio do Aberto-Fechado. Já que
  para cada alteração, deve-se abrir a função
  e alterar o switch.
Use Nomes Descritivos
● Devemos criar nomes que descrevem bem o
  que as funções fazem.
● Princípo de Ward: "Você sabe que está criando
  um código limpo quando cada rotina que você
  lê é como você esperava."
● Metade do esforço para satisfazer essa máxima
  é escolher bons nomes para as funções que
  fazem apenas uma coisa.
● Quanto menor e mais centralizada for a função
  mais fácil será para se pensar em um nome
  descritivo.
Use Nomes Descritivos
● Nomes extensos são maiores do que nomes
  pequenos e enigmáticos.
● Um nome extenso e descritivo é melhor que
  um comentário extenso e descritivo.
● Use uma convenção de nomenaclatura que
  possibilite uma fácil leitura das funções
  com vários nomes.
● Não se preocupe com o tempo para criar
  um nome, e não tenho medo de modificá-lo
  caso tenha encontrado uma opção melhor.
Use Nomes Descritivos
● É comum que ao se buscar nomes
  adequados     resulte    em     uma      boa
  reestruturação do código.
● Seja consistente nos nomes, utilize sempre
  as mesmas frases, substantivos e verbos.
Parâmetros de Função
● O número ideal de argumentos para um
  método é zero.
● Depois, um argumento, mônade, e em
  seguida, dois argumentos, díade.
● Métodos com três argumentos, tríade, ou
  mais, devem ser evitados sempre que
  possível.    Necessitam     de    uma boa
  justificativa caso sejam utilizados.
Parâmetros de Função
● Parâmetros são complicados. Eles requerem
  bastante conceito. Nos exemplos eles foram
  até retirados.
● É    mais    fácil  enteder  o    método:
  includeSetupPage() do que o método:
  includeSetupPageInto(newPage-Content).
Parâmetros de Função
● Os     parâmetros     são    ainda     mais
  problemáticos do ponto de vista de testes.
● Imagine criar todos os cenários de testes
  posíveis para todas as combinações
  existentes entre os parâmetros.
● Se não houver nenhum parâmetro, esta é
  uma tarefa simples, se já existir um, não é
  tão difícil assim.
● Com dois a situação já passa a ser
  desafiadora.
Parâmetros da Função
● Os parâmetros de saída são ainda mais
  difíces de entender do que os de entrada.
● Geralmente não esperamos dados saídos por
  parâmetros.
● Um parâmetro de entrada é a melhor coisa
  depois do zero parâmetro.
●É facil entender:
  ○ SetupTeardown-Includer.render(pageData)
  ○ E fica bem claro que renderizemos os dados em
    pageData.
Formas Mônades Comuns
● Há duas razões comuns para se passar um
  único parâmetro para uma função:
  ○ Você pode estar fazendo uma pergunta sobre
    aquele parâmetro:
    ■ boolean fileExists(“MyFile”).
  ○ Você pode estar trabalhando aquele parâmetro,
    transformando-o em outra coisa e retornando-o
    ■ InputStream fileOpen(“MyFile”)
    ■ Transforma a String do nome de um arquivo em
       um valor retornado pela InputStream.
Formas Mônades Comuns
● Outra forma menos comum é para a
  utilização de eventos:
  ○ Há um parâmetro de entrada, mas não há um de
    saida.
  ○ O programa em si serve para interpretar a chamada
    da função como um evento, e usar o parâmetro
    para alterar o estado do sistema.
  ○ void passwordAttemptFailedNtimes(int attempts).
Formas Mônades Comuns
● Tente evitar funções que não sigam estas
  formas, como:
  ○ void includeSetupPageInto(StringBuffer pageText)
● Usar um parâmetro de saída em vez de um
  valor de retorno para uma modificação fica
  confuso.
● Se uma função vai transformar o seu
  parâmetro de entrada, a alteração deve
  aparecer como o valor retornado.
Parâmetros Lógicos
● "Parâmetros lógicos são feios".
● Utilizar um valor booleano como parâmetro
  em uma função é certamente uma prática
  horrível, pois ele complica imediatamente a
  assinatura     do     método,     mostrando
  explicitamente que o método faz mais de
  uma coisa.
Exemplo
● Um método: render(true) é difícil de ser
  interpretado por um leitor simples.
● Ele fica melhor: render(boolean isSuite),
  mas nem tanto.
● O melhor seria dividí-lo em:
  ○ renderForSuite() e
  ○ renderForSingleTest().
Funções Díades
● Uma função com dois parâmetros é mais fácil
  de enteder do que uma com apenas um. A
  função writeField(name) é mais fácil de
  compreender do que a writeField(output-
  Stream, name).
● Embora as duas estejam claras, a primeira
  apresenta seu propósito explicitamente quando
  lemos.
● Já a segunda requer uma pequena pausa até
  que aprendemos a ignorar o primeiro
  parâmetro.
Funções Díades
● E é ai que mora o problema, porque é nas
  partes do código que ignoramos que mora o
  problema.
● Díades não são ruins, e certamente terão de
  ser utilizá-dos. Entretanto deve-se estar
  ciente de que haverá um preço a pagar e,
  portanto, deve-se em tirar proveito dos
  mecanismos disponíveis a você para
  convertê-los em mônades.
Tríades
● Funções que recebem três parâmetros são
  consideravelmente     mais   difíceis  de
  entender do que as que utiliza ois
  parâmetros.
● A questão de ordenação, pausa, ignoração
  apresentam mais do que o dobro de
  dificuldade.
● Portanto as utilize somente quando houver
  extrema necessidade.
Tríades - Exemplo
● assertEquals(message, expected, actual).
● O parâmetro message precisa ser deduzido,
  e as vezes não é entendido pelo
  programados qual é a sua função.
Tríades - Exemplo 2
● Um método como:
  ○ Circle makeCircle(double x, double y, double radius)
● Ser transformado para:
  ○ Circle makeCircle(Point center, double radius);
● Pode parecer uma trapaça, mas x e y são
  partes de um conceito maior e merecer ter
  uma denominação diferenciada.
Nomenclatura
● Como dito anteriormente, é importante que
  as funções tenham nomes que expliquem
  diretamente o que elas fazem.
● Mas tão importante quanto isso, é que estes
  nomes também relacionem como o
  parâmetro vai interagir com a função.
Nomenclatura - Exemplos
● Em caso de de mônades a função e o
  parâmetro devem ser criados baseados em
  um bom par de verbo/substantivo.
  ○ write(name)
● O que quer que seja o parâmetro "name",
  sebemos que é ele que será "escrito"
  (write).
● Um nome melhor ainda seria:
  ○ writeField(name)
● Que nos dias ainda que o nome é um campo
  (field).
Evite Efeitos Colaterais
● "Efeitos colaterais são mentiras".
● Você promete fazer uma coisa com a sua
  função, mas ela faz outras coisas
  escondidas, isto é errado.
● Veremos no exemplo a seguir o que seria
  um exemplo de efeito colateral em um
  sistema que está fazendo login.
Evite Efeitos Colaterais - Exemplo
Evite Efeitos Colaterais
● O efeito colateral deste código está na
  linha:
  ○ Session.initialize();
● Pelo nome da função (checkPassword), ela
  verifica a senha, mas não é dito que ela
  inicia a sessão.
● Então alguém que acredita no que diz o
  nome da função, correrá o risco de apagar
  todos os dados da sessão existente caso ele
  deseje autenticar o usuário.
Evite Efeitos Colaterais
● Este efeito colateral cria um acoplamento
  temporário.
● Esta função só poderá ser chamada em
  casos específicos (quando for seguro
  inicializar a sessão).
● Se for chamada fora de ordem sem querer,
  os dados serão perdidos.
● Um nome melhor para o método poderia se:
  ○ checkPasswordAndInitializeSession
Parâmetros de Saída
● Parâmetros são comumente interpretados
  como entradas de uma função.
● Quando encontramos parâmetros de saída
  em alguma função, temos que gastar um
  tempo bem maior para ler e relê-la.
● Como por exemplo:
  ○ appendFooter(s);
● Esta função anexa s como um rodapé
  (footer) em algo? Ou anexa um rodapé a s?
● s é uma entrada ou uma saída?
Parâmetros de Saída
● Analisando a assinatura da função:
  ○ public void appendFooter(StringBuffer report);
● A questão é esclarecida, mas a custa da
  verificação da declaração da função.
● Isto é considerado uma relida, uma
  iterrupção de raciocínio e deve ser evitado.
● De modo geral deve-se evitar parâmetros
  de saída. Uma utilização melhor do método
  seria:
  ○ report.appendFooter();
Parâmetros de Saída
● Caso a função precise alterar o estado de
  algo, faça-a mudar o estado do objeto a
  que pertence.
Separação Comando-Consulta
● Funções devem fazer algo ou responder a
  algo. Mas nunca as duas coisas.
● Sua função ou altera o estado de um objeto
  ou retorna informações sobre ele.
● Efetuar as duas tarefas gera confusão.
Separação Comando-Consulta
Exemplo
● Analisando o método:
  ○ public boolean set(String attribute, String value);
● Esta função define o valor de um dado
  atributo e retorna verdadeiro se obtiver
  êxito e falso se tal atributo não existir.
● Isto leva a instruções estranhas que podem
  ser difíceis de serem interpretadas como:
  ○ if (set("username", "unclebob"))...
Separação Comando-Consulta
Exemplo
● Do ponto de vista de um leitor:
   ○ Está perguntando se o atributo "username"
     anteriormente recebeu o valor "unclebob"?
   ○ Ou se "username" obtêve êxito ao receber o valor
     "ubclebob"?
● Fica difícil adivinhar.
Prefira Exceções a Retorno de Código
de Erro
● Fazer funções retornarem códigos de erros
  é uma leve violação da separação comando-
  consulta.
● Estruturas deste tipo podem gerar trechos
  de códigos aninhados, fazendo com que o
  erro deve ser tratado imediatamente.
● Com a utilização de exções podemos tratar
  os erros em separado.
Exemplo Ruim
Exemplo Bom
Extraia os Blocos de Try/Catch
● Blocos de código de Try/Catch são
  particularmente "feios" a seu modo.
● Por isso, é melhor extrair os corpos de try e
  catch em funções fora da sua própria
  estrutura.
● Como no exemplo a seguir:
Extraia os Blocos de Try/Catch
Exemplo
Tratamento de Erro é uma Coisa Só
● Funções devem fazer apenas uma coisa.
● Tratamento de erro é uma coisa.
● Criar classes de erro em java, como a
  seguir, não é interessante.
Tratamento de Erro é uma Coisa Só
● Classes como estas são "chamarizes a
  dependência".
● Muitas outras classes devem importá-las e
  usá-las.
● O que coloca uma pressão na classe Error.
● Os programadores não querem colocar
  novos erros para não ter que recompilar.
● A melhor maneira de evitar isto é utilizando
  exceções.
Evite Reptição
● As vezes não é fácil identificar repetição de
  código,consequentemente arrumar erros em
  repetições são difíceis.
● Repetições causam trabalhos dobrados caso
  o código precisa ser modificados.
● Repetição de código é o mal de toda
  progamação.
Exemplo Reptição
Exemplo Repetição
Programação Estruturada
● Conceito de Edsger Dijkstra.
● Cada função deve ter apenas uma entrada e
  uma saída.
● Não há muita vantagem em seguir essa
  estrutura em funções pequenas.
● Se você conseguir manter funções
  pequenas, instruções como return, break e
  continue podem sem vantajosas.
● GoTo nunca deve ser utilizado.
Como escrever Funções como Esta?
● Não é um processo rápido, envolvem vários
  passos.
● Primeiro pense em como resolver o
  problema e faça da maneira que desejar.
● Só depois vá refinando as funções e
  aplicando as regras explicadas no capítulo
  para que fiquem melhores estruturadas.
● Não hesite em decompor toda uma classe se
  sentir necessário, valerá a pena no futuro.
Conclusão
● Funções são os verbos do sistema.
● As Funções são essenciais para o
  entendimento do sistema.
● As funções precisam ajudar o
  funcionamento do sistema.
● Funções precisam ser curtas, bem
  nomeadas, e bem organizadas.

More Related Content

Viewers also liked

Viewers also liked (17)

Tabela de derivada e integral
Tabela de derivada e integralTabela de derivada e integral
Tabela de derivada e integral
 
Endemias
EndemiasEndemias
Endemias
 
Influenza A
Influenza AInfluenza A
Influenza A
 
Regras da matemática
Regras da matemáticaRegras da matemática
Regras da matemática
 
Surto, Epidemia, Pandemia e Endemia
Surto, Epidemia, Pandemia e EndemiaSurto, Epidemia, Pandemia e Endemia
Surto, Epidemia, Pandemia e Endemia
 
Endemias e epidemias
Endemias e epidemiasEndemias e epidemias
Endemias e epidemias
 
Números naturais i final
Números naturais i finalNúmeros naturais i final
Números naturais i final
 
1 regras básicas de matemática
1 regras básicas de matemática  1 regras básicas de matemática
1 regras básicas de matemática
 
Operações com Números Naturais
Operações com Números NaturaisOperações com Números Naturais
Operações com Números Naturais
 
Números Inteiros
Números InteirosNúmeros Inteiros
Números Inteiros
 
Multiplicação e divisão de inteiros
Multiplicação e divisão de inteirosMultiplicação e divisão de inteiros
Multiplicação e divisão de inteiros
 
Regra de sinais da matemática
Regra de sinais da matemáticaRegra de sinais da matemática
Regra de sinais da matemática
 
Conjunto dos Números Inteiros
Conjunto dos Números Inteiros Conjunto dos Números Inteiros
Conjunto dos Números Inteiros
 
Bioestadística
BioestadísticaBioestadística
Bioestadística
 
Números inteiros
Números inteirosNúmeros inteiros
Números inteiros
 
Números naturais
Números naturaisNúmeros naturais
Números naturais
 
Operações com Números Naturais
Operações com Números NaturaisOperações com Números Naturais
Operações com Números Naturais
 

Similar to Código limpo: Funções Capítulo 3

Boas práticas no desenvolvimento de software
Boas práticas no desenvolvimento de softwareBoas práticas no desenvolvimento de software
Boas práticas no desenvolvimento de softwareFelipe
 
TDC 2015 São Paulo - Clean Code para Testers
TDC 2015 São Paulo - Clean Code para TestersTDC 2015 São Paulo - Clean Code para Testers
TDC 2015 São Paulo - Clean Code para TestersStefan Teixeira
 
Livro - código limpo caps (3,4) (clean code)
Livro - código limpo caps (3,4) (clean code)Livro - código limpo caps (3,4) (clean code)
Livro - código limpo caps (3,4) (clean code)André Justi
 
Clean Code (Robert C. Martin)
Clean Code (Robert C. Martin)Clean Code (Robert C. Martin)
Clean Code (Robert C. Martin)Yasser Veleda
 
Refatoração - aquela caprichada no código
Refatoração - aquela caprichada no códigoRefatoração - aquela caprichada no código
Refatoração - aquela caprichada no códigoJuciellen Cabrera
 
Aula 2 - Lógica de Programação
Aula 2 - Lógica de ProgramaçãoAula 2 - Lógica de Programação
Aula 2 - Lógica de ProgramaçãoInstituto CENTEC
 
Removendo o cheiro ruim do seu código - PHPSC Conf 2011
Removendo o cheiro ruim do seu código - PHPSC Conf 2011Removendo o cheiro ruim do seu código - PHPSC Conf 2011
Removendo o cheiro ruim do seu código - PHPSC Conf 2011Luís Cobucci
 
Introdução à programação em Ruby
Introdução à programação em RubyIntrodução à programação em Ruby
Introdução à programação em RubyDaniel Andrade
 

Similar to Código limpo: Funções Capítulo 3 (20)

Codigo limpo
Codigo limpoCodigo limpo
Codigo limpo
 
Boas práticas no desenvolvimento de software
Boas práticas no desenvolvimento de softwareBoas práticas no desenvolvimento de software
Boas práticas no desenvolvimento de software
 
Gisele
GiseleGisele
Gisele
 
Linguagem C - Funções
Linguagem C - FunçõesLinguagem C - Funções
Linguagem C - Funções
 
TDC 2015 São Paulo - Clean Code para Testers
TDC 2015 São Paulo - Clean Code para TestersTDC 2015 São Paulo - Clean Code para Testers
TDC 2015 São Paulo - Clean Code para Testers
 
Livro - código limpo caps (3,4) (clean code)
Livro - código limpo caps (3,4) (clean code)Livro - código limpo caps (3,4) (clean code)
Livro - código limpo caps (3,4) (clean code)
 
Clean Code (Robert C. Martin)
Clean Code (Robert C. Martin)Clean Code (Robert C. Martin)
Clean Code (Robert C. Martin)
 
Clean code part 2
Clean code   part 2Clean code   part 2
Clean code part 2
 
Cap04
Cap04Cap04
Cap04
 
Cap04
Cap04Cap04
Cap04
 
Cap04
Cap04Cap04
Cap04
 
Estudos Technocorp
Estudos TechnocorpEstudos Technocorp
Estudos Technocorp
 
Refatoração - aquela caprichada no código
Refatoração - aquela caprichada no códigoRefatoração - aquela caprichada no código
Refatoração - aquela caprichada no código
 
Clean Code
Clean CodeClean Code
Clean Code
 
Aula 2 - Lógica de Programação
Aula 2 - Lógica de ProgramaçãoAula 2 - Lógica de Programação
Aula 2 - Lógica de Programação
 
Clean code
Clean codeClean code
Clean code
 
01-Paradigmas.pdf
01-Paradigmas.pdf01-Paradigmas.pdf
01-Paradigmas.pdf
 
Removendo o cheiro ruim do seu código - PHPSC Conf 2011
Removendo o cheiro ruim do seu código - PHPSC Conf 2011Removendo o cheiro ruim do seu código - PHPSC Conf 2011
Removendo o cheiro ruim do seu código - PHPSC Conf 2011
 
Python
PythonPython
Python
 
Introdução à programação em Ruby
Introdução à programação em RubyIntrodução à programação em Ruby
Introdução à programação em Ruby
 

More from Inael Rodrigues

Artigo Monitoramento de Pastagem
Artigo Monitoramento de PastagemArtigo Monitoramento de Pastagem
Artigo Monitoramento de PastagemInael Rodrigues
 
Arquiteturas de sistemas reais
Arquiteturas de sistemas reaisArquiteturas de sistemas reais
Arquiteturas de sistemas reaisInael Rodrigues
 
Codigo limpo: Nomes Significativos Cap 2
Codigo limpo:  Nomes Significativos Cap 2Codigo limpo:  Nomes Significativos Cap 2
Codigo limpo: Nomes Significativos Cap 2Inael Rodrigues
 
Código limpo: Comentários
Código limpo:   ComentáriosCódigo limpo:   Comentários
Código limpo: ComentáriosInael Rodrigues
 
Código Limpo: Testes de Unidade Capítulo 09
Código Limpo: Testes de Unidade Capítulo 09 Código Limpo: Testes de Unidade Capítulo 09
Código Limpo: Testes de Unidade Capítulo 09 Inael Rodrigues
 
Código Limpo: Objetos e Estruturas de Dados cap6
Código Limpo: Objetos e Estruturas de Dados cap6Código Limpo: Objetos e Estruturas de Dados cap6
Código Limpo: Objetos e Estruturas de Dados cap6Inael Rodrigues
 
Livro Código Limpo: Tratamento de Erros - Cap 7
Livro Código Limpo: Tratamento de Erros - Cap 7Livro Código Limpo: Tratamento de Erros - Cap 7
Livro Código Limpo: Tratamento de Erros - Cap 7Inael Rodrigues
 
Livro Código limpo: Classes
Livro Código limpo:  ClassesLivro Código limpo:  Classes
Livro Código limpo: ClassesInael Rodrigues
 
Teste Estrutural usando a ferramenta Jabuti
Teste Estrutural usando a ferramenta JabutiTeste Estrutural usando a ferramenta Jabuti
Teste Estrutural usando a ferramenta JabutiInael Rodrigues
 
TDC 2012: Trilha - Android University Back end Android
TDC 2012: Trilha - Android University Back end Android TDC 2012: Trilha - Android University Back end Android
TDC 2012: Trilha - Android University Back end Android Inael Rodrigues
 
TDC 2012 Trilha – Android University
TDC 2012 Trilha – Android UniversityTDC 2012 Trilha – Android University
TDC 2012 Trilha – Android UniversityInael Rodrigues
 
Ferramentas para Ambiente de Desenvolvimento Ágil
Ferramentas para Ambiente de Desenvolvimento ÁgilFerramentas para Ambiente de Desenvolvimento Ágil
Ferramentas para Ambiente de Desenvolvimento ÁgilInael Rodrigues
 
Android bootcamp 06-01-2012 Part 2
Android bootcamp 06-01-2012 Part 2Android bootcamp 06-01-2012 Part 2
Android bootcamp 06-01-2012 Part 2Inael Rodrigues
 
Android bootcamp 06-01-2012 Part 1
Android bootcamp  06-01-2012 Part 1Android bootcamp  06-01-2012 Part 1
Android bootcamp 06-01-2012 Part 1Inael Rodrigues
 

More from Inael Rodrigues (18)

Artigo Monitoramento de Pastagem
Artigo Monitoramento de PastagemArtigo Monitoramento de Pastagem
Artigo Monitoramento de Pastagem
 
Map Reduce
Map ReduceMap Reduce
Map Reduce
 
Arquiteturas de sistemas reais
Arquiteturas de sistemas reaisArquiteturas de sistemas reais
Arquiteturas de sistemas reais
 
Backtracking
BacktrackingBacktracking
Backtracking
 
Codigo limpo: Nomes Significativos Cap 2
Codigo limpo:  Nomes Significativos Cap 2Codigo limpo:  Nomes Significativos Cap 2
Codigo limpo: Nomes Significativos Cap 2
 
Código limpo: Limites
Código limpo: LimitesCódigo limpo: Limites
Código limpo: Limites
 
Código limpo: Comentários
Código limpo:   ComentáriosCódigo limpo:   Comentários
Código limpo: Comentários
 
Código Limpo: Testes de Unidade Capítulo 09
Código Limpo: Testes de Unidade Capítulo 09 Código Limpo: Testes de Unidade Capítulo 09
Código Limpo: Testes de Unidade Capítulo 09
 
Código Limpo: Objetos e Estruturas de Dados cap6
Código Limpo: Objetos e Estruturas de Dados cap6Código Limpo: Objetos e Estruturas de Dados cap6
Código Limpo: Objetos e Estruturas de Dados cap6
 
Livro Código Limpo: Tratamento de Erros - Cap 7
Livro Código Limpo: Tratamento de Erros - Cap 7Livro Código Limpo: Tratamento de Erros - Cap 7
Livro Código Limpo: Tratamento de Erros - Cap 7
 
Livro Código limpo: Classes
Livro Código limpo:  ClassesLivro Código limpo:  Classes
Livro Código limpo: Classes
 
Paa algoritmos gulosos
Paa  algoritmos gulososPaa  algoritmos gulosos
Paa algoritmos gulosos
 
Teste Estrutural usando a ferramenta Jabuti
Teste Estrutural usando a ferramenta JabutiTeste Estrutural usando a ferramenta Jabuti
Teste Estrutural usando a ferramenta Jabuti
 
TDC 2012: Trilha - Android University Back end Android
TDC 2012: Trilha - Android University Back end Android TDC 2012: Trilha - Android University Back end Android
TDC 2012: Trilha - Android University Back end Android
 
TDC 2012 Trilha – Android University
TDC 2012 Trilha – Android UniversityTDC 2012 Trilha – Android University
TDC 2012 Trilha – Android University
 
Ferramentas para Ambiente de Desenvolvimento Ágil
Ferramentas para Ambiente de Desenvolvimento ÁgilFerramentas para Ambiente de Desenvolvimento Ágil
Ferramentas para Ambiente de Desenvolvimento Ágil
 
Android bootcamp 06-01-2012 Part 2
Android bootcamp 06-01-2012 Part 2Android bootcamp 06-01-2012 Part 2
Android bootcamp 06-01-2012 Part 2
 
Android bootcamp 06-01-2012 Part 1
Android bootcamp  06-01-2012 Part 1Android bootcamp  06-01-2012 Part 1
Android bootcamp 06-01-2012 Part 1
 

Código limpo: Funções Capítulo 3

  • 1. Código Limpo Capítulo 3 - Funções Bruno Blumenschein Hélios Kárum de Oliveira Bastos Rodrigo Oliveira Andrade
  • 2. Regras ● Primeira Regra: ○ As funções devem ser pequenas; ● Segunda Regra: ○ "Elas precisam ser ainda menores"; ● Não há como provar porque, foi baseado nas tentativas e erros do autor. ● Não ultrapassar mais do que 20 linhas, com 150 carcteres por linha.
  • 6. Exemplo - Segunda Melhoria
  • 7. Blocos e Identação ● Seguindo a linha de se minimizar funções, instruções como if, else e while devem possuir apenas uma linha de código. ● E provavelmente esta linha será uma chamada a uma função. ● Além de manter a função pequena agrega valor de documentação, já que o nome da função deve ser bem descritivo.
  • 8. Blocos e Identação ● Essa estrutura também implica que as funções não devem ter muitas estruturas aninhadas. ● Para facilitar a estrutura e identação o nível máximo de estruturas aninhadas deve ser de uma ou duas.
  • 9. Fazer apenas uma Coisa ● "Functions should do one thing. They should do it well. The should do it only." ● Funções devem fazer uma única coisa. Elas devem fazê-la bem. Elas devem fazer apenas ela. ● O problema é saber o que é "uma única coisa".
  • 10. Fazer apenas uma Coisa ● O que faz o programa do exemplo anterior (RenderPageWithSetupsAndTeardowns): 1. Determina se a página é de teste; 2. Se for, inclui setUps e tearDowns; 3. Renderiza a página em HTML. ● É apenas uma função ou são três? ● Note que as três operações realizadas estão a um nível abaixo do nome da função. ● Então ela está fazendo uma coisa só.
  • 11. Fazer apenas uma Coisa ● O motivo de criarmos uma função é para 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.
  • 12. Seções em Funções ● Funções que fazem apenas apenas uma coisa não podem ser razoavelmente divididas em seções. ● Caso isto aconteça é um sintoma de estar fazendo mais de uma coisa.
  • 13. Um Nível de Abstração por Função ● A fim de confirmar se uma função só faz uma coisa, precisamos verificar se todas as intruções dentro da função estão no mesmo nível de abstração. ● Vários níveis de abstração dentro de uma função sempre geram confusão. ● Os leitores podem não conseguir dizer se uma expressão determinada é um conceito essêncial ou um mero detalhe.
  • 14. Ler o Código de Cima para Baixo ● O código deve ser lido de maneira top- down. ● Desejamos que cada função seja seguida pelas outras no próximo nível de abstração, de modo que possamos ler o programa um nível de cada vez. ● Chamamos isso de regra descendente.
  • 15. Exemplo ● Para incluir setups e teardowns, nós incluimos primeiro os setups, depois nós incluimos o conteúdo da página de testes, e então incluimos os teardowns; ● Para incluir os setups, nós incluimos o suite setup se for uma suite, e então incluimos o setup regular; ● Para incluir o suite setup, nós procuramos na hierarquia pela página "SuiteSetUp", e então adicionamos uma instrução com o caminho para aquela página. ● Para procurar a hierarquia a cima...
  • 16. Ler o Código de Cima para Baixo ● Acaba sendo difícil para o programador aplicar essa regra, mas quando ele passa a dominar esse truque, ele passa a ter o controle de verificação para saber se uma função só faz apenas uma coisa.
  • 17. Switch ● É difícil criarmos um swtich pequeno. ● Mesmo o menor switch possível, com dois casos, já é maior do que eu gostaria de ter em um único bloco de código. ● É difícil criar um switch que faça apenas uma coisa. ● Pela sua natureza eles são criados para fazerem N coisas. ● Infelizemente nós não podemos evitar o uso de switchs.
  • 18. Switch ● Mas nós podemos nos assegurar que cada instrução está um nível de abstração abaixo e que nunca se repetem. ● Switch geralmente tem vários problemas com o Principio do Aberto-Fechado. Já que para cada alteração, deve-se abrir a função e alterar o switch.
  • 19. Use Nomes Descritivos ● Devemos criar nomes que descrevem bem o que as funções fazem. ● Princípo de Ward: "Você sabe que está criando um código limpo quando cada rotina que você lê é como você esperava." ● Metade do esforço para satisfazer essa máxima é escolher bons nomes para as funções que fazem apenas uma coisa. ● Quanto menor e mais centralizada for a função mais fácil será para se pensar em um nome descritivo.
  • 20. Use Nomes Descritivos ● Nomes extensos são maiores do que nomes pequenos e enigmáticos. ● Um nome extenso e descritivo é melhor que um comentário extenso e descritivo. ● Use uma convenção de nomenaclatura que possibilite uma fácil leitura das funções com vários nomes. ● Não se preocupe com o tempo para criar um nome, e não tenho medo de modificá-lo caso tenha encontrado uma opção melhor.
  • 21. Use Nomes Descritivos ● É comum que ao se buscar nomes adequados resulte em uma boa reestruturação do código. ● Seja consistente nos nomes, utilize sempre as mesmas frases, substantivos e verbos.
  • 22. Parâmetros de Função ● O número ideal de argumentos para um método é zero. ● Depois, um argumento, mônade, e em seguida, dois argumentos, díade. ● Métodos com três argumentos, tríade, ou mais, devem ser evitados sempre que possível. Necessitam de uma boa justificativa caso sejam utilizados.
  • 23. Parâmetros de Função ● Parâmetros são complicados. Eles requerem bastante conceito. Nos exemplos eles foram até retirados. ● É mais fácil enteder o método: includeSetupPage() do que o método: includeSetupPageInto(newPage-Content).
  • 24. Parâmetros de Função ● Os parâmetros são ainda mais problemáticos do ponto de vista de testes. ● Imagine criar todos os cenários de testes posíveis para todas as combinações existentes entre os parâmetros. ● Se não houver nenhum parâmetro, esta é uma tarefa simples, se já existir um, não é tão difícil assim. ● Com dois a situação já passa a ser desafiadora.
  • 25. Parâmetros da Função ● Os parâmetros de saída são ainda mais difíces de entender do que os de entrada. ● Geralmente não esperamos dados saídos por parâmetros. ● Um parâmetro de entrada é a melhor coisa depois do zero parâmetro. ●É facil entender: ○ SetupTeardown-Includer.render(pageData) ○ E fica bem claro que renderizemos os dados em pageData.
  • 26. Formas Mônades Comuns ● Há duas razões comuns para se passar um único parâmetro para uma função: ○ Você pode estar fazendo uma pergunta sobre aquele parâmetro: ■ boolean fileExists(“MyFile”). ○ Você pode estar trabalhando aquele parâmetro, transformando-o em outra coisa e retornando-o ■ InputStream fileOpen(“MyFile”) ■ Transforma a String do nome de um arquivo em um valor retornado pela InputStream.
  • 27. Formas Mônades Comuns ● Outra forma menos comum é para a utilização de eventos: ○ Há um parâmetro de entrada, mas não há um de saida. ○ O programa em si serve para interpretar a chamada da função como um evento, e usar o parâmetro para alterar o estado do sistema. ○ void passwordAttemptFailedNtimes(int attempts).
  • 28. Formas Mônades Comuns ● Tente evitar funções que não sigam estas formas, como: ○ void includeSetupPageInto(StringBuffer pageText) ● Usar um parâmetro de saída em vez de um valor de retorno para uma modificação fica confuso. ● Se uma função vai transformar o seu parâmetro de entrada, a alteração deve aparecer como o valor retornado.
  • 29. Parâmetros Lógicos ● "Parâmetros lógicos são feios". ● Utilizar um valor booleano como parâmetro em uma função é certamente uma prática horrível, pois ele complica imediatamente a assinatura do método, mostrando explicitamente que o método faz mais de uma coisa.
  • 30. Exemplo ● Um método: render(true) é difícil de ser interpretado por um leitor simples. ● Ele fica melhor: render(boolean isSuite), mas nem tanto. ● O melhor seria dividí-lo em: ○ renderForSuite() e ○ renderForSingleTest().
  • 31. Funções Díades ● Uma função com dois parâmetros é mais fácil de enteder do que uma com apenas um. A função writeField(name) é mais fácil de compreender do que a writeField(output- Stream, name). ● Embora as duas estejam claras, a primeira apresenta seu propósito explicitamente quando lemos. ● Já a segunda requer uma pequena pausa até que aprendemos a ignorar o primeiro parâmetro.
  • 32. Funções Díades ● E é ai que mora o problema, porque é nas partes do código que ignoramos que mora o problema. ● Díades não são ruins, e certamente terão de ser utilizá-dos. Entretanto deve-se estar ciente de que haverá um preço a pagar e, portanto, deve-se em tirar proveito dos mecanismos disponíveis a você para convertê-los em mônades.
  • 33. Tríades ● Funções que recebem três parâmetros são consideravelmente mais difíceis de entender do que as que utiliza ois parâmetros. ● A questão de ordenação, pausa, ignoração apresentam mais do que o dobro de dificuldade. ● Portanto as utilize somente quando houver extrema necessidade.
  • 34. Tríades - Exemplo ● assertEquals(message, expected, actual). ● O parâmetro message precisa ser deduzido, e as vezes não é entendido pelo programados qual é a sua função.
  • 35. Tríades - Exemplo 2 ● Um método como: ○ Circle makeCircle(double x, double y, double radius) ● Ser transformado para: ○ Circle makeCircle(Point center, double radius); ● Pode parecer uma trapaça, mas x e y são partes de um conceito maior e merecer ter uma denominação diferenciada.
  • 36. Nomenclatura ● Como dito anteriormente, é importante que as funções tenham nomes que expliquem diretamente o que elas fazem. ● Mas tão importante quanto isso, é que estes nomes também relacionem como o parâmetro vai interagir com a função.
  • 37. Nomenclatura - Exemplos ● Em caso de de mônades a função e o parâmetro devem ser criados baseados em um bom par de verbo/substantivo. ○ write(name) ● O que quer que seja o parâmetro "name", sebemos que é ele que será "escrito" (write). ● Um nome melhor ainda seria: ○ writeField(name) ● Que nos dias ainda que o nome é um campo (field).
  • 38. Evite Efeitos Colaterais ● "Efeitos colaterais são mentiras". ● Você promete fazer uma coisa com a sua função, mas ela faz outras coisas escondidas, isto é errado. ● Veremos no exemplo a seguir o que seria um exemplo de efeito colateral em um sistema que está fazendo login.
  • 40. Evite Efeitos Colaterais ● O efeito colateral deste código está na linha: ○ Session.initialize(); ● Pelo nome da função (checkPassword), ela verifica a senha, mas não é dito que ela inicia a sessão. ● Então alguém que acredita no que diz o nome da função, correrá o risco de apagar todos os dados da sessão existente caso ele deseje autenticar o usuário.
  • 41. Evite Efeitos Colaterais ● Este efeito colateral cria um acoplamento temporário. ● Esta função só poderá ser chamada em casos específicos (quando for seguro inicializar a sessão). ● Se for chamada fora de ordem sem querer, os dados serão perdidos. ● Um nome melhor para o método poderia se: ○ checkPasswordAndInitializeSession
  • 42. Parâmetros de Saída ● Parâmetros são comumente interpretados como entradas de uma função. ● Quando encontramos parâmetros de saída em alguma função, temos que gastar um tempo bem maior para ler e relê-la. ● Como por exemplo: ○ appendFooter(s); ● Esta função anexa s como um rodapé (footer) em algo? Ou anexa um rodapé a s? ● s é uma entrada ou uma saída?
  • 43. Parâmetros de Saída ● Analisando a assinatura da função: ○ public void appendFooter(StringBuffer report); ● A questão é esclarecida, mas a custa da verificação da declaração da função. ● Isto é considerado uma relida, uma iterrupção de raciocínio e deve ser evitado. ● De modo geral deve-se evitar parâmetros de saída. Uma utilização melhor do método seria: ○ report.appendFooter();
  • 44. Parâmetros de Saída ● Caso a função precise alterar o estado de algo, faça-a mudar o estado do objeto a que pertence.
  • 45. Separação Comando-Consulta ● Funções devem fazer algo ou responder a algo. Mas nunca as duas coisas. ● Sua função ou altera o estado de um objeto ou retorna informações sobre ele. ● Efetuar as duas tarefas gera confusão.
  • 46. Separação Comando-Consulta Exemplo ● Analisando o método: ○ public boolean set(String attribute, String value); ● Esta função define o valor de um dado atributo e retorna verdadeiro se obtiver êxito e falso se tal atributo não existir. ● Isto leva a instruções estranhas que podem ser difíceis de serem interpretadas como: ○ if (set("username", "unclebob"))...
  • 47. Separação Comando-Consulta Exemplo ● Do ponto de vista de um leitor: ○ Está perguntando se o atributo "username" anteriormente recebeu o valor "unclebob"? ○ Ou se "username" obtêve êxito ao receber o valor "ubclebob"? ● Fica difícil adivinhar.
  • 48. Prefira Exceções a Retorno de Código de Erro ● Fazer funções retornarem códigos de erros é uma leve violação da separação comando- consulta. ● Estruturas deste tipo podem gerar trechos de códigos aninhados, fazendo com que o erro deve ser tratado imediatamente. ● Com a utilização de exções podemos tratar os erros em separado.
  • 51. Extraia os Blocos de Try/Catch ● Blocos de código de Try/Catch são particularmente "feios" a seu modo. ● Por isso, é melhor extrair os corpos de try e catch em funções fora da sua própria estrutura. ● Como no exemplo a seguir:
  • 52. Extraia os Blocos de Try/Catch Exemplo
  • 53. Tratamento de Erro é uma Coisa Só ● Funções devem fazer apenas uma coisa. ● Tratamento de erro é uma coisa. ● Criar classes de erro em java, como a seguir, não é interessante.
  • 54. Tratamento de Erro é uma Coisa Só ● Classes como estas são "chamarizes a dependência". ● Muitas outras classes devem importá-las e usá-las. ● O que coloca uma pressão na classe Error. ● Os programadores não querem colocar novos erros para não ter que recompilar. ● A melhor maneira de evitar isto é utilizando exceções.
  • 55. Evite Reptição ● As vezes não é fácil identificar repetição de código,consequentemente arrumar erros em repetições são difíceis. ● Repetições causam trabalhos dobrados caso o código precisa ser modificados. ● Repetição de código é o mal de toda progamação.
  • 58. Programação Estruturada ● Conceito de Edsger Dijkstra. ● Cada função deve ter apenas uma entrada e uma saída. ● Não há muita vantagem em seguir essa estrutura em funções pequenas. ● Se você conseguir manter funções pequenas, instruções como return, break e continue podem sem vantajosas. ● GoTo nunca deve ser utilizado.
  • 59. Como escrever Funções como Esta? ● Não é um processo rápido, envolvem vários passos. ● Primeiro pense em como resolver o problema e faça da maneira que desejar. ● Só depois vá refinando as funções e aplicando as regras explicadas no capítulo para que fiquem melhores estruturadas. ● Não hesite em decompor toda uma classe se sentir necessário, valerá a pena no futuro.
  • 60. Conclusão ● Funções são os verbos do sistema. ● As Funções são essenciais para o entendimento do sistema. ● As funções precisam ajudar o funcionamento do sistema. ● Funções precisam ser curtas, bem nomeadas, e bem organizadas.