
Índice

Reek é uma ferramenta que examina classes de rubi, módulos e métodos e relata que qualquer código cheire a encontrar.
Para uma excelente introdução ao código, cheiros e reek, consulte esta postagem no blog ou aquela. Há também essa conversa de Rubyconfby (também há um deck de slide, se você preferir).
Instale -o via rubygems:
gem install reeke execute assim:
reek [options] [dir_or_source_file] * Imagine uma demo.rb de arquivo de origem.rb contendo:
# Smelly class
class Smelly
# This will reek of UncommunicativeMethodName
def x
y = 10 # This will reek of UncommunicativeVariableName
end
endReek relatará o seguinte código cheira neste arquivo:
$ reek --no-documentation demo.rb
Inspecting 1 file(s):
S
demo.rb -- 2 warnings:
[4]:UncommunicativeMethodName: Smelly#x has the name 'x'
[5]:UncommunicativeVariableName: Smelly#x has the variable name 'y'
Reek é oficialmente apoiado para o Cruby 3.0 a 3,3 e para Jruby 9.4. Outras implementações do Ruby (como Rubinius) não são oficialmente apoiadas, mas também devem funcionar.
Observe que, em cada versão do Ruby, Reek usará o analisador para a versão do Ruby. Portanto, você deve sempre correr Reek usando uma das versões de rubi de destino do seu projeto.
Reek se concentra no cheiro de código de alto nível, por isso não podemos dizer como consertar avisos de maneira genérica; Isso é e sempre dependerá completamente da sua linguagem de domínio e da lógica de negócios.
Dito isto, um exemplo pode ajudá -lo a continuar. Dê uma olhada nesta amostra de um modelo Ruby on Rails (esteja ciente de que isso é truncado, não o código de trabalho):
class ShoppingCart < ActiveRecord :: Base
has_many :items
def gross_price
items . sum { | item | item . net + item . tax }
end
end
class Item < ActiveRecord :: Base
belongs_to :shopping_cart
endRecupendo reek neste arquivo como este:
reek app/models/shopping_cart.rb
relataria:
[5, 5]:ShoppingCart#gross_price refers to item more than self (FeatureEnvy)
Corrigir isso é bem direto. Coloque o cálculo bruto de preços para um único item onde ele pertence, que seria a classe Item :
class ShoppingCart < ActiveRecord :: Base
has_many :items
def gross_price
items . sum { | item | item . gross_price }
end
end
class Item < ActiveRecord :: Base
belongs_to :shopping_cart
def gross_price
net + tax
end
endO Código Cheira Documentos pode dar a você mais dicas - verifique os primeiros quando você tiver um aviso com o qual não sabe lidar.
Existem várias maneiras pelas quais você pode reek trabalhar em fontes, o mais comum apenas sendo
reek lib/Se você não passar nenhum argumento de origem para cheirar, apenas o diretório de trabalho atual como fonte.
Então
reeké exatamente a mesma coisa que ser explícito:
reek .Além disso, você pode canalizar o código para cheirar assim:
echo " class C; def m; end; end " | reekIsso imprimiria:
$stdin -- 3 warnings:
[1]:C has no descriptive comment (IrresponsibleModule)
[1]:C has the name ' C ' (UncommunicativeModuleName)
[1]:C#m has the name ' m ' (UncommunicativeMethodName)Atualmente, o Reek inclui verificações para alguns aspectos do casal de controle, aglomerado de dados, inveja de recursos, classe grande, lista de parâmetros longos, polimorfismo simulado, muitas declarações, nome não comunicativo, parâmetros não utilizados e muito mais. Consulte o código cheira a detalhes atualizados exatamente do que reek verificará seu código.
Configuração especial para detectores controversos:
O método privado não utilizado é desativado por padrão, porque é meio controverso, o que significa que você precisa ativá -lo explicitamente em sua configuração via
UnusedPrivateMethod :
enabled : trueA função de utilidade também é um detector controverso que pode ser realmente implacável. Como conseqüência, tornamos possível desativá-lo para métodos não públicos como este:
---
UtilityFunction :
public_methods_only : true Para uma visão geral básica, execute
reek -- helpPara um resumo dessas opções da CLI, consulte as opções da linha de comando.
Configurar o Reek através de um arquivo de configuração é de longe a maneira mais poderosa. Reek espera que esse nome de arquivo seja .reek.yml , mas você pode substituir isso através do comutador CLI -c (veja abaixo).
Existem três maneiras de passar o arquivo de configuração:
-c (consulte a interface da linha de comando acima)A ordem em que o Reek tenta encontrar um arquivo de configuração é exatamente o acima: Primeiro, ele verifica se fornecemos um arquivo de configuração explicitamente via CLI; Em seguida, ele verifica o diretório de trabalho atual para um arquivo e, se não conseguir encontrar um, eleva os diretórios até atingir o diretório raiz; Por fim, ele verifica seu diretório inicial.
Assim que Reek detectar um arquivo de configuração, ele para de pesquisar imediatamente, o que significa que do ponto de vista de Reek existe exatamente um arquivo de configuração e uma configuração, independentemente de quantos arquivos *.reek você pode ter no seu sistema de arquivos.
Nós nos esforçamos muito para tornar a configuração de Reek o mais explicativa possível, então a melhor maneira de entendê -la é analisando um exemplo simples (por exemplo .reek.yml em seu diretório de projeto):
---
# ## Generic smell configuration
detectors :
# You can disable smells completely
IrresponsibleModule :
enabled : false
# You can use filters to silence Reek warnings.
# Either because you simply disagree with Reek (we are not the police) or
# because you want to fix this at a later point in time.
NestedIterators :
exclude :
- " MyWorker#self.class_method " # should be refactored
- " AnotherWorker#instance_method " # should be refactored as well
# A lot of smells allow fine tuning their configuration. You can look up all available options
# in the corresponding smell documentation in /docs. In most cases you probably can just go
# with the defaults as documented in defaults.reek.yml.
DataClump :
max_copies : 3
min_clump_size : 3
# ## Directory specific configuration
# You can configure smells on a per-directory base.
# E.g. the classic Rails case: controllers smell of NestedIterators (see /docs/Nested-Iterators.md) and
# helpers smell of UtilityFunction (see docs/Utility-Function.md)
#
# Note that we only allow configuration on a directory level, not a file level,
# so all paths have to point to directories.
# A Dir.glob pattern can be used.
directories :
" web_app/app/controllers " :
NestedIterators :
enabled : false
" web_app/app/helpers** " :
UtilityFunction :
enabled : false
" web_app/lib/**/test/** " :
UtilityFunction :
enabled : false
# ## Excluding directories
# Directories and files below will not be scanned at all
exclude_paths :
- lib/legacy
- lib/rake/legacy_tasks
- lib/smelly.rbComo você vê acima, a configuração de Reek consiste em 3 seções diferentes denotadas por 3 chaves diferentes:
Tudo o que você adicionar à sua configuração deve ser escopo sob uma dessas chaves.
Se você possui uma diretiva de diretório para a qual existe uma diretiva padrão, a mais específica (que é a diretiva de diretório) terá precedência.
Esta configuração, por exemplo:
---
detectors :
IrresponsibleModule :
enabled : false
TooManyStatements :
max_statements : 5
directories :
" app/controllers " :
TooManyStatements :
max_statements : 10traduz para:
Todo detector de cheiro suporta nossas opções básicas de cheiro. Como você pode ver acima, certos tipos de cheiro oferecem uma configuração que vai além da das opções básicas de cheiro, por exemplo, um grupo de dados. Todas as opções que vão além das opções básicas de cheiro estão documentadas na página de tipo de cheiro correspondente /documentos (se você deseja obter uma visão geral rápida sobre todas as configurações possíveis, também pode conferir o arquivo defaults.reek.yml neste repositório.
Observe que você não precisa de um arquivo de configuração. Se você está bem com todos os padrões que definimos, pode pular isso completamente.
Não se preocupe em introduzir um erro em seu arquivo de configuração que possa passar despercebido - o Reek usa um esquema para validar sua configuração contra o Start Up e falhará em voz alta, caso você tenha escrito uma opção ou usou o tipo de dados errado para um valor como este:
Error: We found some problems with your configuration file: [/detectors/DetectorWithTypo] key 'DetectorWithTypo:' is undefined.
Reek pega um arquivo de configuração e um arquivo de configuração apenas com .reek.yml sendo o nome padrão.
Caso você precise ter um ou mais arquivos de configuração no diretório (por exemplo, você está brincando com configurações diferentes e mutuamente exclusivas), você precisa dizer a Reek explicitamente qual arquivo usar via reek -c config.reek .
Caso você precise suprimir um aviso de cheiro e não pode ou não deseja usar arquivos de configuração por qualquer motivo que você também possa usar comentários especiais de código -fonte como este:
# This method smells of :reek:NestedIterators
def smelly_method foo
foo . each { | bar | bar . each { | baz | baz . qux } }
endVocê pode até passar no cheiro de configurações específicas de configuração:
# :reek:NestedIterators { max_allowed_nesting: 2 }
def smelly_method foo
foo . each { | bar | bar . each { | baz | baz . qux } }
endEssa é uma característica incrivelmente poderosa e explicada ainda mais sob a supressão do cheiro.
Com o mecanismo dinâmico do Reeks de encontrar um arquivo de configuração, você pode encontrar uma situação em que não tem 100% de certeza de que arquivo de configuração está usando. Por exemplo, você tem um arquivo de configuração específico do projeto no seu projeto ROOT e também em outra configuração de reek no seu diretório doméstico que você usa para todos os seus outros projetos e, por qualquer motivo.
Nesse caso, você pode passar o sinalizador --show-configuration-path para reek, o que fará com que o reek produza o caminho para o arquivo de configuração que está usando.
A integração de ferramentas como Reek em uma base de código maior existente pode ser assustadora quando você precisa consertar possivelmente centenas ou milhares de avisos de cheiro primeiro. Claro que você pode desativar manualmente avisos de cheiro como mostrados acima, mas dependendo do tamanho da sua base de código, isso pode não ser uma opção. Felizmente, Reek fornece uma bandeira 'TODO' que você pode usar para gerar uma configuração que suprimirá todos os avisos do cheiro para a base de código atual:
reek --todo lib/Isso criará o arquivo '.reek.yml' em seu diretório de trabalho atual.
Você pode usar isso como sua configuração - como seu diretório de trabalho provavelmente é o seu projeto ROOT Na maioria dos casos, você não precisa dizer a Reek explicitamente para usar '.reek.yml' porque o Reek o pega automaticamente e usá -lo como arquivo de configuração. Consulte o carregamento de configuração acima.
Se, por qualquer motivo, você decidir colocar '.reek.yml' em outro lugar onde o reek não o pegue automaticamente, você precisa dizer a Reek explicitamente para fazê -lo via:
reek -c whatever/.reek.yml lib/ É importante entender que o caso de uso número um do sinalizador --todo deve ser executado uma vez no início da introdução do Reek para facilitar a transição. Se você se encontrar querendo reek reek com a bandeira --todo para silenciar muitos novos avisos, você está derrotando o objetivo da bandeira --todo e do próprio Reek.
Como conseqüência, correr com a bandeira --todo novamente não substituirá um '.reek.yml' existente e, em vez disso, abortará a execução. Também não levará nenhum outro arquivo de configuração que você possa ter em consideração.
Isso significa que quando você corre
reek -c other_configuration.reek --todo lib/ other_configuration.reek serão simplesmente ignorados.
É claro que você sempre pode excluir o arquivo .reek.yml existente e, em seguida, executar o reek com o sinalizador --todo , mas lembre -se de que este não é o caso de uso pretendido desse recurso.
Além do óbvio
reek [options] [dir_or_source_file] *Existem algumas outras maneiras de usar o Reek em seus projetos:
A primeira coisa que você deseja fazer depois de verificar o código -fonte é executar o Bundler:
bundle install
e depois execute os testes:
bundle exec rspec spec/your/file_spec.rb # Runs all tests in spec/your/file_spec.rb
bundle exec rspec spec/your/file_spec.rb:23 # Runs test in line 23
bundle exec cucumber features/your_file.feature # Runs all scenarios in your_file.feature
bundle exec cucumber features/your_file.feature:23 # Runs scenario at line 23Ou apenas execute o conjunto de testes inteiro:
bundle exec rake
Isso executará os testes (RSPEC e pepino), Rubocop e próprio reek.
Outra tarefa de ancinho útil é a tarefa console . Isso o jogará direto em um ambiente onde você pode brincar com módulos e classes Reeks:
bundle exec rake console
irb(main):001> Reek::Examiner
=> Reek::Examiner
Você também pode usar o IRB enquanto executa os testes adicionando o seguinte no ponto em que deseja começar a depurar:
binding . irbDê uma olhada na nossa API de desenvolvedor para obter mais inspiração.
A partir de então você deve conferir:
Se você não sentir vontade de sujar as mãos com o código, ainda existem outras maneiras de nos ajudar:
Se você encontrar problemas climáticos de código (por exemplo, repasse o limite de duplicação de código), poderá querer executar o clima de código contra a base de código Reek localmente. Para fazer isso, você precisa fazer o seguinte:
gem install codeclimatecodeclimate engines:install Agora você pode executar vários motores climáticos de código, por exemplo, codeclimate analyze -e duplication
Reek suporta 6 formatos de saída:
--format html )--format yaml , veja também relatórios da YAML)--format json )--format xml )--format github ) Fazer o reek "Rails"-amigável é bastante simples, pois apoiamos configurações específicas do diretório ( directory directives em Reek Talk). Basta adicionar isso ao seu arquivo de configuração:
directories :
" app/controllers " :
IrresponsibleModule :
enabled : false
NestedIterators :
max_allowed_nesting : 2
UnusedPrivateMethod :
enabled : false
InstanceVariableAssumption :
enabled : false
" app/helpers " :
IrresponsibleModule :
enabled : false
UtilityFunction :
enabled : false
" app/mailers " :
InstanceVariableAssumption :
enabled : false
" app/models " :
InstanceVariableAssumption :
enabled : falseTenha cuidado, porém, o Reek não mescla suas entradas de configuração; portanto, se você já possui uma diretiva de diretório para "aplicativos/controladores" ou "aplicativo/ajudante", precisa atualizar essas diretivas em vez de copiar a amostra YAML acima em seu arquivo de configuração.
Uma lista não exaustiva de outros analisadores de código estáticos que você pode querer examinar:
A equipe do Reek Core consiste em:
O autor original de Reek é Kevin Rutherford.
O autor do logotipo de Reek é Sonja Heinen.
Contribuições notáveis vieram de: