128
Analisando Complexidade de Código Ruby Utilizando Métricas para Encontrar Código que Fede Cássio Marques RubyMasters Conf 2011 Saturday, February 26, 2011

Analisando Complexidade de Código Ruby

Embed Size (px)

DESCRIPTION

Palestra feita no evento Ruby Masters Conf edição 2011.

Citation preview

Page 1: Analisando Complexidade de Código Ruby

Analisando Complexidade de Código Ruby

Utilizando Métricas para Encontrar Código que Fede

Cássio MarquesRubyMasters Conf 2011

Saturday, February 26, 2011

Page 2: Analisando Complexidade de Código Ruby

Cássio Marques

• código + comida vegan + livros + skate + música

• Taoweb

• Lime

• http://cassiomarques.wordpress.com

• @cassiomarques

Saturday, February 26, 2011

Page 3: Analisando Complexidade de Código Ruby

Porque analisar o código?

Saturday, February 26, 2011

Page 4: Analisando Complexidade de Código Ruby

http://www.flickr.com/photos/rovingi/312078231/Saturday, February 26, 2011

Page 5: Analisando Complexidade de Código Ruby

Como analisar o código?

Saturday, February 26, 2011

Page 6: Analisando Complexidade de Código Ruby

Estética

Saturday, February 26, 2011

Page 7: Analisando Complexidade de Código Ruby

Dificuldade de Manutenção

Saturday, February 26, 2011

Page 8: Analisando Complexidade de Código Ruby

Chute

Saturday, February 26, 2011

Page 9: Analisando Complexidade de Código Ruby

Abstrações

Saturday, February 26, 2011

Page 10: Analisando Complexidade de Código Ruby

Métricas

Saturday, February 26, 2011

Page 11: Analisando Complexidade de Código Ruby

Medir alguma propriedade específica

do código

Saturday, February 26, 2011

Page 12: Analisando Complexidade de Código Ruby

Objetivo: Quantificar o que antes era abstrato

Saturday, February 26, 2011

Page 13: Analisando Complexidade de Código Ruby

Métrica ABC

Saturday, February 26, 2011

Page 14: Analisando Complexidade de Código Ruby

Analisa Complexidade

Saturday, February 26, 2011

Page 15: Analisando Complexidade de Código Ruby

floggithub.com/seattlerb/flog

Saturday, February 26, 2011

Page 16: Analisando Complexidade de Código Ruby

AssignementDefinir o valor de uma variável explicitamente

Saturday, February 26, 2011

Page 17: Analisando Complexidade de Código Ruby

=*=/=-=

+=<<

etc...

Saturday, February 26, 2011

Page 18: Analisando Complexidade de Código Ruby

BranchingCriar um novo fluxo de execução

Saturday, February 26, 2011

Page 19: Analisando Complexidade de Código Ruby

ifelse

elsif (argh!)caseand

orrescueuntilwhile

Saturday, February 26, 2011

Page 20: Analisando Complexidade de Código Ruby

CallsChamadas a métodos

Saturday, February 26, 2011

Page 21: Analisando Complexidade de Código Ruby

(Outras implementações usam Condition)

Saturday, February 26, 2011

Page 22: Analisando Complexidade de Código Ruby

|ABC| = sqrt((A*A)+(B*B)+(C*C))

Saturday, February 26, 2011

Page 23: Analisando Complexidade de Código Ruby

Mas em Ruby temos mais do que isso!

Saturday, February 26, 2011

Page 24: Analisando Complexidade de Código Ruby

eval & cia(pontuação alta!!!)

define_methodeval

module_evalclass_eval

instance_eval

Saturday, February 26, 2011

Page 25: Analisando Complexidade de Código Ruby

blocos/yield

Saturday, February 26, 2011

Page 26: Analisando Complexidade de Código Ruby

instance_methodmethod_defined?

private_instance_methodprivante_class_methodpublic_instance_method

etc...

Introspecção

Saturday, February 26, 2011

Page 27: Analisando Complexidade de Código Ruby

Module#includedModule#extendedClass#inheritedmethod_defined

etc...

Hooks

Saturday, February 26, 2011

Page 28: Analisando Complexidade de Código Ruby

Ou seja...

Saturday, February 26, 2011

Page 29: Analisando Complexidade de Código Ruby

Ou seja...METAPROGRAMAÇÃO É COMPLEXO E DIFICULTA

A MANUTENÇÃO DO CÓDIGO

Saturday, February 26, 2011

Page 30: Analisando Complexidade de Código Ruby

Quando verificar isso no seu código?

Saturday, February 26, 2011

Page 31: Analisando Complexidade de Código Ruby

Frequentemente

Saturday, February 26, 2011

Page 32: Analisando Complexidade de Código Ruby

(já deixei para a fase final de um projeto e o

resultado foi traumático)

Saturday, February 26, 2011

Page 33: Analisando Complexidade de Código Ruby

Complexidade Ciclomática

Saturday, February 26, 2011

Page 34: Analisando Complexidade de Código Ruby

saikurohttp://saikuro.rubyforge.org/

Saturday, February 26, 2011

Page 35: Analisando Complexidade de Código Ruby

Mede o número de segmentos linearmente

independentes na execução do código

Saturday, February 26, 2011

Page 36: Analisando Complexidade de Código Ruby

Grafo direcionado para representar os

caminhos de execução

Saturday, February 26, 2011

Page 37: Analisando Complexidade de Código Ruby

1 def some_method(value) 2 if value % 2 == 0 3 value.times { |i| puts i } 4 else 5 while value >= 0 6 puts value 7 value -= 1 8 end 9 end10 end

Saturday, February 26, 2011

Page 38: Analisando Complexidade de Código Ruby

Início

value % 2 == 0

value.times { |i| ...

puts i

while value >= 0

puts value -= 1

puts value

Fim

Saturday, February 26, 2011

Page 39: Analisando Complexidade de Código Ruby

C = A - V + 2PC => Complexidade ciclomática

A => Número de arestas

V => Número de vértices

P => Número de componentes conectados

Saturday, February 26, 2011

Page 40: Analisando Complexidade de Código Ruby

Pode ser utilizada para definir o número de casos de teste necessários para

ter total cobertura do código

Saturday, February 26, 2011

Page 41: Analisando Complexidade de Código Ruby

Métrica procedural, mas pode ser usada em código OO no escopo

de métodos

Saturday, February 26, 2011

Page 42: Analisando Complexidade de Código Ruby

Duplicação de código

Saturday, February 26, 2011

Page 43: Analisando Complexidade de Código Ruby

flayhttp://ruby.sadi.st/Flay.html

Saturday, February 26, 2011

Page 44: Analisando Complexidade de Código Ruby

Pesquisa por códigos SEMELHANTES

Saturday, February 26, 2011

Page 45: Analisando Complexidade de Código Ruby

Resultados são bons candidatos para

refactoring

Saturday, February 26, 2011

Page 46: Analisando Complexidade de Código Ruby

Código que muda com muita frequência

Saturday, February 26, 2011

Page 47: Analisando Complexidade de Código Ruby

churngithub.com/danmayer/churn

Saturday, February 26, 2011

Page 48: Analisando Complexidade de Código Ruby

Código que muda muito == problemas

Saturday, February 26, 2011

Page 49: Analisando Complexidade de Código Ruby

Indica quantidade de alterações ao longo do

tempo

Saturday, February 26, 2011

Page 50: Analisando Complexidade de Código Ruby

MétodosClasses

Arquivos

Saturday, February 26, 2011

Page 51: Analisando Complexidade de Código Ruby

git/mercurial

Saturday, February 26, 2011

Page 52: Analisando Complexidade de Código Ruby

Code Smells

Saturday, February 26, 2011

Page 53: Analisando Complexidade de Código Ruby

Sintoma que indica algum problema mais

sério

Saturday, February 26, 2011

Page 54: Analisando Complexidade de Código Ruby

O código pode feder por vários motivos

Saturday, February 26, 2011

Page 55: Analisando Complexidade de Código Ruby

reekgithub.com/kevinrutherford/reek

Saturday, February 26, 2011

Page 56: Analisando Complexidade de Código Ruby

Aceita opções sobre quais smells identificar/

ignorar

Saturday, February 26, 2011

Page 57: Analisando Complexidade de Código Ruby

Atributos

Saturday, February 26, 2011

Page 58: Analisando Complexidade de Código Ruby

readers/writers (ou getters/setters) podem

expor demais seus objetos

Saturday, February 26, 2011

Page 59: Analisando Complexidade de Código Ruby

Variáveis de Classe

Saturday, February 26, 2011

Page 60: Analisando Complexidade de Código Ruby

1 class MyClass2 @@my_class_variable = 13 4 class << self5 attr_accessor :my_other_class_variable6 end7 end

Saturday, February 26, 2011

Page 61: Analisando Complexidade de Código Ruby

Aumenta o escopo global

Saturday, February 26, 2011

Page 62: Analisando Complexidade de Código Ruby

Classe Longa

Saturday, February 26, 2011

Page 63: Analisando Complexidade de Código Ruby

Muitas linhas

Saturday, February 26, 2011

Page 64: Analisando Complexidade de Código Ruby

Muitas variáveis de instância

Saturday, February 26, 2011

Page 65: Analisando Complexidade de Código Ruby

Muitos métodos

Saturday, February 26, 2011

Page 66: Analisando Complexidade de Código Ruby

*provavelmente*fazendo coisa demais!

Saturday, February 26, 2011

Page 67: Analisando Complexidade de Código Ruby

Método Longo

Saturday, February 26, 2011

Page 68: Analisando Complexidade de Código Ruby

Lista de Parâmetros Longa

Saturday, February 26, 2011

Page 69: Analisando Complexidade de Código Ruby

1 def pay_with_credit_card(number, security_code, holder_name, expiration, value)2 # ...3 end

Saturday, February 26, 2011

Page 70: Analisando Complexidade de Código Ruby

Possíveis soluções

Saturday, February 26, 2011

Page 71: Analisando Complexidade de Código Ruby

Passar um hash

Saturday, February 26, 2011

Page 72: Analisando Complexidade de Código Ruby

Encapsular em um objeto

Saturday, February 26, 2011

Page 73: Analisando Complexidade de Código Ruby

Baixa Coesão

Feature Envy

Saturday, February 26, 2011

Page 74: Analisando Complexidade de Código Ruby

1 class Cart2 def price3 @item.price + @item.tax4 end5 end

Saturday, February 26, 2011

Page 75: Analisando Complexidade de Código Ruby

Baixa Coesão

Utility Function

Saturday, February 26, 2011

Page 76: Analisando Complexidade de Código Ruby

Método que não depende do estado do

objeto

Saturday, February 26, 2011

Page 77: Analisando Complexidade de Código Ruby

1 class Oven2 def formatted_temperature(sensor)3 "#{sensor.temperature} #{sensor.unit}"4 end5 end

Saturday, February 26, 2011

Page 78: Analisando Complexidade de Código Ruby

Polimorfismo Simulado

Saturday, February 26, 2011

Page 79: Analisando Complexidade de Código Ruby

1 def some_method(value) 2 if value > 10 3 if value < 20 4 if value != 15 5 puts "duh" 6 else 7 puts "meh" 8 end 9 end10 end11 end

Saturday, February 26, 2011

Page 80: Analisando Complexidade de Código Ruby

switch também :)

(o reek ainda não identifica)

Saturday, February 26, 2011

Page 81: Analisando Complexidade de Código Ruby

Uncommunicative Names

Saturday, February 26, 2011

Page 82: Analisando Complexidade de Código Ruby

Nomes não refletem a intenção do código

Saturday, February 26, 2011

Page 83: Analisando Complexidade de Código Ruby

1 class SomeClass 2 def some_method 3 # ... 4 end 5 6 def some_method_2 7 # ... 8 end 9 10 def another_method11 a = 1012 aLocalVariable = 2513 end14 end

Saturday, February 26, 2011

Page 84: Analisando Complexidade de Código Ruby

Pode ser configurado com uma lista de regexps

default [/^.[0-9]*$/]

Saturday, February 26, 2011

Page 85: Analisando Complexidade de Código Ruby

Cobertura de Teste

Saturday, February 26, 2011

Page 86: Analisando Complexidade de Código Ruby

!= “bem testado”

Saturday, February 26, 2011

Page 87: Analisando Complexidade de Código Ruby

rcovhttp://eigenclass.org/hiki.rb?rcov

Saturday, February 26, 2011

Page 88: Analisando Complexidade de Código Ruby

Pode indicar trechos do código que foram

negligenciados

Saturday, February 26, 2011

Page 89: Analisando Complexidade de Código Ruby

Too Simple To Break

Saturday, February 26, 2011

Page 90: Analisando Complexidade de Código Ruby

Novas funcionalidades são adicionadas, mas continua sem testes

Saturday, February 26, 2011

Page 91: Analisando Complexidade de Código Ruby

Saturday, February 26, 2011

Page 92: Analisando Complexidade de Código Ruby

Saturday, February 26, 2011

Page 93: Analisando Complexidade de Código Ruby

Outros smellse

erros de estilo

Saturday, February 26, 2011

Page 94: Analisando Complexidade de Código Ruby

roodigithub.com/martinjandrews/roodi

Saturday, February 26, 2011

Page 95: Analisando Complexidade de Código Ruby

Atribuição de valor dentro de uma

estrutura condicional

Saturday, February 26, 2011

Page 96: Analisando Complexidade de Código Ruby

1 # Deveria ser foo == 1002 if foo = 1003 # ...4 end

Saturday, February 26, 2011

Page 97: Analisando Complexidade de Código Ruby

1 # Falso positivo...2 def some_method(value)3 if @value = value4 # ...5 end6 end

Saturday, February 26, 2011

Page 98: Analisando Complexidade de Código Ruby

case sem cláusula else

Saturday, February 26, 2011

Page 99: Analisando Complexidade de Código Ruby

1 def some_method(value)2 case value3 when 1..104 puts "Entre 1 e 10"5 when 11..206 puts "Entre 11 e 20"7 end8 end

Saturday, February 26, 2011

Page 100: Analisando Complexidade de Código Ruby

Classes com muitas linhas de código

(por padrão limita em 300)

Saturday, February 26, 2011

Page 101: Analisando Complexidade de Código Ruby

Padrão para nome de classes e módulos

(verifica se o nome das classes e módulos está em CamelCase)

Saturday, February 26, 2011

Page 102: Analisando Complexidade de Código Ruby

cláusulas rescue vazias

Saturday, February 26, 2011

Page 103: Analisando Complexidade de Código Ruby

1 def calculate_factor(number)2 begin3 SOME_CONSTANT / number4 rescue5 6 end7 end

Saturday, February 26, 2011

Page 104: Analisando Complexidade de Código Ruby

1 def calculate_factor(number)2 begin3 SOME_CONSTANT / number4 rescue => e5 # Tratar a exceção de alguma forma...6 end7 end

Saturday, February 26, 2011

Page 105: Analisando Complexidade de Código Ruby

Uso de loops com for

Saturday, February 26, 2011

Page 106: Analisando Complexidade de Código Ruby

1 def print_list(list)2 for value in list do3 puts value4 end5 end

Saturday, February 26, 2011

Page 107: Analisando Complexidade de Código Ruby

1 def print_list(list)2 list.each {|value| puts value }3 end

Saturday, February 26, 2011

Page 108: Analisando Complexidade de Código Ruby

Métodos com muitas linhas de código

(por padrão limita em 20)

Saturday, February 26, 2011

Page 109: Analisando Complexidade de Código Ruby

Padrão para nomes de métodos

(verifica se os nomes dos métodos estão snake_case)

Saturday, February 26, 2011

Page 110: Analisando Complexidade de Código Ruby

github.com/flyerhzm/rails_best_practices

rails_best_practices

Saturday, February 26, 2011

Page 111: Analisando Complexidade de Código Ruby

Ok...

Saturday, February 26, 2011

Page 112: Analisando Complexidade de Código Ruby

Mas é muita coisa para gerenciar!

Saturday, February 26, 2011

Page 113: Analisando Complexidade de Código Ruby

http://metric-fu.rubyforge.org/

metric_fu

Saturday, February 26, 2011

Page 114: Analisando Complexidade de Código Ruby

saikuro + flog + flay + rcov + reek + roodi + churn +

rails_best_practices

Saturday, February 26, 2011

Page 115: Analisando Complexidade de Código Ruby

rake metrics:all

Saturday, February 26, 2011

Page 116: Analisando Complexidade de Código Ruby

Integração Contínua

Saturday, February 26, 2011

Page 117: Analisando Complexidade de Código Ruby

Métricas ao longo do tempo

Saturday, February 26, 2011

Page 118: Analisando Complexidade de Código Ruby

Relatórios!

Saturday, February 26, 2011

Page 119: Analisando Complexidade de Código Ruby

Saturday, February 26, 2011

Page 120: Analisando Complexidade de Código Ruby

Saturday, February 26, 2011

Page 121: Analisando Complexidade de Código Ruby

Saturday, February 26, 2011

Page 122: Analisando Complexidade de Código Ruby

Saturday, February 26, 2011

Page 123: Analisando Complexidade de Código Ruby

Problema:

Saturday, February 26, 2011

Page 124: Analisando Complexidade de Código Ruby

O metric_fu acaba virando uma dependência

do seu projeto

Saturday, February 26, 2011

Page 125: Analisando Complexidade de Código Ruby

github.com/iain/metrical

metrical

Saturday, February 26, 2011

Page 126: Analisando Complexidade de Código Ruby

$ gem install metrical$ cd /path/of/your/project$ metrical

Saturday, February 26, 2011

Page 127: Analisando Complexidade de Código Ruby

Dúvidas?

Saturday, February 26, 2011

Page 128: Analisando Complexidade de Código Ruby

Obrigado!

Saturday, February 26, 2011