Analisando Complexidade de Código Ruby

Post on 18-Dec-2014

3.706 views 0 download

description

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

Transcript of 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

Cássio Marques

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

• Taoweb

• Lime

• http://cassiomarques.wordpress.com

• @cassiomarques

Saturday, February 26, 2011

Porque analisar o código?

Saturday, February 26, 2011

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

Como analisar o código?

Saturday, February 26, 2011

Estética

Saturday, February 26, 2011

Dificuldade de Manutenção

Saturday, February 26, 2011

Chute

Saturday, February 26, 2011

Abstrações

Saturday, February 26, 2011

Métricas

Saturday, February 26, 2011

Medir alguma propriedade específica

do código

Saturday, February 26, 2011

Objetivo: Quantificar o que antes era abstrato

Saturday, February 26, 2011

Métrica ABC

Saturday, February 26, 2011

Analisa Complexidade

Saturday, February 26, 2011

floggithub.com/seattlerb/flog

Saturday, February 26, 2011

AssignementDefinir o valor de uma variável explicitamente

Saturday, February 26, 2011

=*=/=-=

+=<<

etc...

Saturday, February 26, 2011

BranchingCriar um novo fluxo de execução

Saturday, February 26, 2011

ifelse

elsif (argh!)caseand

orrescueuntilwhile

Saturday, February 26, 2011

CallsChamadas a métodos

Saturday, February 26, 2011

(Outras implementações usam Condition)

Saturday, February 26, 2011

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

Saturday, February 26, 2011

Mas em Ruby temos mais do que isso!

Saturday, February 26, 2011

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

define_methodeval

module_evalclass_eval

instance_eval

Saturday, February 26, 2011

blocos/yield

Saturday, February 26, 2011

instance_methodmethod_defined?

private_instance_methodprivante_class_methodpublic_instance_method

etc...

Introspecção

Saturday, February 26, 2011

Module#includedModule#extendedClass#inheritedmethod_defined

etc...

Hooks

Saturday, February 26, 2011

Ou seja...

Saturday, February 26, 2011

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

A MANUTENÇÃO DO CÓDIGO

Saturday, February 26, 2011

Quando verificar isso no seu código?

Saturday, February 26, 2011

Frequentemente

Saturday, February 26, 2011

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

resultado foi traumático)

Saturday, February 26, 2011

Complexidade Ciclomática

Saturday, February 26, 2011

saikurohttp://saikuro.rubyforge.org/

Saturday, February 26, 2011

Mede o número de segmentos linearmente

independentes na execução do código

Saturday, February 26, 2011

Grafo direcionado para representar os

caminhos de execução

Saturday, February 26, 2011

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

Início

value % 2 == 0

value.times { |i| ...

puts i

while value >= 0

puts value -= 1

puts value

Fim

Saturday, February 26, 2011

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

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

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

de métodos

Saturday, February 26, 2011

Duplicação de código

Saturday, February 26, 2011

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

Saturday, February 26, 2011

Pesquisa por códigos SEMELHANTES

Saturday, February 26, 2011

Resultados são bons candidatos para

refactoring

Saturday, February 26, 2011

Código que muda com muita frequência

Saturday, February 26, 2011

churngithub.com/danmayer/churn

Saturday, February 26, 2011

Código que muda muito == problemas

Saturday, February 26, 2011

Indica quantidade de alterações ao longo do

tempo

Saturday, February 26, 2011

MétodosClasses

Arquivos

Saturday, February 26, 2011

git/mercurial

Saturday, February 26, 2011

Code Smells

Saturday, February 26, 2011

Sintoma que indica algum problema mais

sério

Saturday, February 26, 2011

O código pode feder por vários motivos

Saturday, February 26, 2011

reekgithub.com/kevinrutherford/reek

Saturday, February 26, 2011

Aceita opções sobre quais smells identificar/

ignorar

Saturday, February 26, 2011

Atributos

Saturday, February 26, 2011

readers/writers (ou getters/setters) podem

expor demais seus objetos

Saturday, February 26, 2011

Variáveis de Classe

Saturday, February 26, 2011

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

Saturday, February 26, 2011

Aumenta o escopo global

Saturday, February 26, 2011

Classe Longa

Saturday, February 26, 2011

Muitas linhas

Saturday, February 26, 2011

Muitas variáveis de instância

Saturday, February 26, 2011

Muitos métodos

Saturday, February 26, 2011

*provavelmente*fazendo coisa demais!

Saturday, February 26, 2011

Método Longo

Saturday, February 26, 2011

Lista de Parâmetros Longa

Saturday, February 26, 2011

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

Saturday, February 26, 2011

Possíveis soluções

Saturday, February 26, 2011

Passar um hash

Saturday, February 26, 2011

Encapsular em um objeto

Saturday, February 26, 2011

Baixa Coesão

Feature Envy

Saturday, February 26, 2011

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

Saturday, February 26, 2011

Baixa Coesão

Utility Function

Saturday, February 26, 2011

Método que não depende do estado do

objeto

Saturday, February 26, 2011

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

Saturday, February 26, 2011

Polimorfismo Simulado

Saturday, February 26, 2011

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

switch também :)

(o reek ainda não identifica)

Saturday, February 26, 2011

Uncommunicative Names

Saturday, February 26, 2011

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

Saturday, February 26, 2011

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

Pode ser configurado com uma lista de regexps

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

Saturday, February 26, 2011

Cobertura de Teste

Saturday, February 26, 2011

!= “bem testado”

Saturday, February 26, 2011

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

Saturday, February 26, 2011

Pode indicar trechos do código que foram

negligenciados

Saturday, February 26, 2011

Too Simple To Break

Saturday, February 26, 2011

Novas funcionalidades são adicionadas, mas continua sem testes

Saturday, February 26, 2011

Saturday, February 26, 2011

Saturday, February 26, 2011

Outros smellse

erros de estilo

Saturday, February 26, 2011

roodigithub.com/martinjandrews/roodi

Saturday, February 26, 2011

Atribuição de valor dentro de uma

estrutura condicional

Saturday, February 26, 2011

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

Saturday, February 26, 2011

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

Saturday, February 26, 2011

case sem cláusula else

Saturday, February 26, 2011

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

Classes com muitas linhas de código

(por padrão limita em 300)

Saturday, February 26, 2011

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

cláusulas rescue vazias

Saturday, February 26, 2011

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

Saturday, February 26, 2011

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

Uso de loops com for

Saturday, February 26, 2011

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

Saturday, February 26, 2011

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

Saturday, February 26, 2011

Métodos com muitas linhas de código

(por padrão limita em 20)

Saturday, February 26, 2011

Padrão para nomes de métodos

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

Saturday, February 26, 2011

github.com/flyerhzm/rails_best_practices

rails_best_practices

Saturday, February 26, 2011

Ok...

Saturday, February 26, 2011

Mas é muita coisa para gerenciar!

Saturday, February 26, 2011

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

metric_fu

Saturday, February 26, 2011

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

rails_best_practices

Saturday, February 26, 2011

rake metrics:all

Saturday, February 26, 2011

Integração Contínua

Saturday, February 26, 2011

Métricas ao longo do tempo

Saturday, February 26, 2011

Relatórios!

Saturday, February 26, 2011

Saturday, February 26, 2011

Saturday, February 26, 2011

Saturday, February 26, 2011

Saturday, February 26, 2011

Problema:

Saturday, February 26, 2011

O metric_fu acaba virando uma dependência

do seu projeto

Saturday, February 26, 2011

github.com/iain/metrical

metrical

Saturday, February 26, 2011

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

Saturday, February 26, 2011

Dúvidas?

Saturday, February 26, 2011

Obrigado!

Saturday, February 26, 2011