
Tabla de contenido

Reek es una herramienta que examina las clases, módulos y métodos rubíes e informa que cualquier código huele que encuentre.
Para obtener una excelente introducción a los olores de código y apagar, consulte esta publicación de blog o esa. También está esta charla de Rubyconfby (también hay un mazo de diapositivas si lo prefiere).
Instálelo a través de Rubygems:
gem install reeky ejecutarlo así:
reek [options] [dir_or_source_file] * Imagine un archivo fuente demo.rb que contiene:
# Smelly class
class Smelly
# This will reek of UncommunicativeMethodName
def x
y = 10 # This will reek of UncommunicativeVariableName
end
endReek informará el siguiente código huele en este archivo:
$ 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 es oficialmente admitido para Cruby 3.0 a 3.3 y para Jruby 9.4. Otras implementaciones de Ruby (como Rubinius) no son compatibles oficialmente, pero también deberían funcionar.
Tenga en cuenta que, en cada versión de Ruby, Reek usará el analizador para esa versión de Ruby. Por lo tanto, siempre debe ejecutar a Reek usando una de las versiones Ruby Target de su proyecto.
Reek se centra en los olores de código de alto nivel, por lo que no podemos decirle cómo arreglar las advertencias de manera genérica; Esto siempre dependerá completamente de su lenguaje de dominio y lógica comercial.
Dicho esto, un ejemplo podría ayudarlo a ponerse en marcha. Eche un vistazo a esta muestra de un modelo Ruby on Rails (tenga en cuenta que esto es truncado, no código de trabajo):
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
endEjecutando a Reek en este archivo como este:
reek app/models/shopping_cart.rb
informaría:
[5, 5]:ShoppingCart#gross_price refers to item more than self (FeatureEnvy)
Arreglar esto es bastante sencillo. Ponga el cálculo del precio bruto para un solo artículo donde pertenece, que sería la clase 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
endLos documentos de Code Smells pueden darle más sugerencias: asegúrese de verlos primero cuando tenga una advertencia con la que no sabe cómo lidiar.
Hay múltiples formas en que puede tener trabajo en fuentes, el más común es solo ser
reek lib/Si no aprueba ningún argumento de origen para reejarlo, solo toma el directorio de trabajo actual como fuente.
Entonces
reekes exactamente lo mismo que ser explícito:
reek .Además, puede tuve el código para apasionar así:
echo " class C; def m; end; end " | reekEsto se imprimiría:
$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)REEK actualmente incluye comprobaciones de algunos aspectos de la pareja de control, el grupo de datos, la envidia de funciones, la clase grande, la lista de parámetros largos, el polimorfismo simulado, demasiadas declaraciones, nombre poco comunicativo, parámetros no utilizados y más. Consulte el código Huele para obtener detalles actualizados de exactamente lo que Reek verificará su código.
Configuración especial para detectores controvertidos:
El método privado no utilizado está deshabilitado de forma predeterminada porque es un poco controvertido, lo que significa que debe activarlo explícitamente en su configuración a través de
UnusedPrivateMethod :
enabled : trueLa función de utilidad también es un detector controvertido que puede ser realmente implacable. Como consecuencia, hicimos posible deshabilitarlo para métodos no públicos como este:
---
UtilityFunction :
public_methods_only : true Para una descripción general básica, ejecute
reek -- helpPara obtener un resumen de esas opciones de CLI, consulte Opciones de línea de comandos.
Configurar a Reek a través de un archivo de configuración es, con mucho, la forma más potente. Reek espera que este nombre de archivo sea .reek.yml , pero puede anular esto a través del interruptor CLI -c (ver más abajo).
Hay tres formas de aprobar Reek el archivo de configuración:
-c (consulte la interfaz de línea de comandos arriba)El orden en el que Reek intenta encontrar dicho archivo de configuración es exactamente el anterior: primero verifica si le hemos dado un archivo de configuración explícitamente a través de CLI; Luego verifica el directorio de trabajo actual para un archivo y si no puede encontrar uno, atraviesa los directorios hasta que llega al directorio raíz; Por último, verifica su directorio de inicio.
Tan pronto como Reek detecta un archivo de configuración, deja de buscar de inmediato, lo que significa que desde el punto de vista de Reek existe exactamente un archivo de configuración y una configuración, independientemente de cuántos archivos *.reek pueda tener en su sistema de archivos.
Ponemos mucho esfuerzo en hacer que la configuración de Reek sea lo más explicativa posible, por lo que la mejor manera de entenderlo es observando un ejemplo simple (por ejemplo , .reek.yml en el directorio de su proyecto):
---
# ## 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 puede ver anteriormente, la configuración de Reek consta de 3 secciones diferentes denotadas por 3 claves diferentes:
Lo que agregue a su configuración debe alcanzar una de esas claves.
Si tiene una directiva de directorio para la cual existe una directiva predeterminada, la más específica (que es la Directiva de Directorio) tendrá prioridad.
Esta configuración, por ejemplo:
---
detectors :
IrresponsibleModule :
enabled : false
TooManyStatements :
max_statements : 5
directories :
" app/controllers " :
TooManyStatements :
max_statements : 10se traduce en:
Cada detector de olor es compatible con nuestras opciones básicas de olor. Como puede ver anteriormente, ciertos tipos de olfato ofrecen una configuración que va más allá de la de las opciones de olor básicas, por ejemplo, Data Splump. Todas las opciones que van más allá de las opciones de olor básicas se documentan en la página de Tipo /Docs de olor correspondiente (si desea obtener una descripción general rápida sobre todas las configuraciones posibles, también puede consultar el archivo defaults.reek.yml en este repositorio.
Tenga en cuenta que no necesita un archivo de configuración en absoluto. Si está bien con todos los valores predeterminados que establecemos, puede omitir esto por completo.
No se preocupe por introducir un error en su archivo de configuración que pueda pasar desapercibido: Reek usa un esquema para validar su configuración en el inicio del inicio y fallará en voz alta en caso de que haya mal escritura una opción o haya usado el tipo de datos incorrecto para un valor como este:
Error: We found some problems with your configuration file: [/detectors/DetectorWithTypo] key 'DetectorWithTypo:' is undefined.
Reek toma un archivo de configuración y un archivo de configuración solo con .reek.yml es el nombre predeterminado.
En caso de que tenga que tener uno o más archivos de configuración en el directorio (por ejemplo, está jugando con configuraciones diferentes y mutuamente excluyentes), debe decirle a Reek explícitamente qué archivo utilizará a través de reek -c config.reek .
En caso de que necesite suprimir una advertencia de olor y no puede o no desea usar archivos de configuración por cualquier razón, también puede usar comentarios especiales del código fuente como este:
# This method smells of :reek:NestedIterators
def smelly_method foo
foo . each { | bar | bar . each { | baz | baz . qux } }
endIncluso puede pasar la configuración de configuración específica del olor:
# :reek:NestedIterators { max_allowed_nesting: 2 }
def smelly_method foo
foo . each { | bar | bar . each { | baz | baz . qux } }
endEsta es una característica increíblemente poderosa y se explica más bajo la supresión del olor.
Con Reeks Mecanismo dinámico para encontrar un archivo de configuración, puede encontrar una situación en la que no esté 100% seguro de qué archivo de configuración está utilizando REEK. Por ejemplo, tiene un archivo de configuración específico del proyecto en la raíz de su proyecto y también en otra configuración de Reek en su directorio de inicio que usa para todos sus otros proyectos y por cualquier razón, Reek parece estar usando otro archivo de configuración que el que supuso que lo haría.
En este caso, puede pasar la bandera --show-configuration-path para reek, lo que hará que Reek genere la ruta al archivo de configuración que está utilizando.
La integración de herramientas como Reek en una base de código más grande existente puede ser desalentador cuando tienes que arreglar posiblemente cientos o miles de advertencias de olor. Claro que puede deshabilitar manualmente las advertencias de olor como se muestra arriba, pero dependiendo del tamaño de su base de código, esta podría no ser una opción. Afortunadamente, Reek proporciona un indicador 'TODO' que puede usar para generar una configuración que suprima todas las advertencias de olor a la base de código actual:
reek --todo lib/Esto creará el archivo '.reek.yml' en su directorio de trabajo actual.
Luego puede usar esto como su configuración, ya que su directorio de trabajo probablemente sea la raíz de su proyecto en la mayoría de los casos, no tiene que decirle a Reek explícitamente que use '.reek.yml' porque Reek lo recogerá automáticamente y lo usará como archivo de configuración. Consulte la carga de la configuración anterior.
Si por cualquier razón que decida poner '.reek.yml' en otro lugar donde Reek no lo recoja automáticamente, debe decirle a Reek explícitamente que lo haga a través de:
reek -c whatever/.reek.yml lib/ Es importante comprender que el caso de uso número uno de la bandera --todo se ejecutará una vez al comienzo de la introducción de Reek para aliviar la transición. Si te encuentras con ganas de volver a manejar con la bandera --todo para silenciar muchas advertencias nuevas, estás derrotando el propósito de la bandera --todo y de reek.
Como consecuencia, ejecutar a Reek con la bandera --todo nuevamente no sobrescribirá un '.reek.yml' existente y en su lugar abortará la ejecución. Tampoco tendrá en cuenta ningún otro archivo de configuración que pueda tener.
Esto significa que cuando corres
reek -c other_configuration.reek --todo lib/ other_configuration.reek simplemente será ignorado.
Por supuesto, siempre puede eliminar el archivo .reek.yml existente y luego ejecutar Reek con el indicador --todo , pero tenga en cuenta que este no es el caso de uso previsto de esta característica.
Además de lo obvio
reek [options] [dir_or_source_file] *Hay bastantes otras formas de usar a Reek en sus proyectos:
Lo primero que desea hacer después de revisar el código fuente es ejecutar Bundler:
bundle install
y luego ejecute las pruebas:
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 23O simplemente ejecute toda la suite de prueba:
bundle exec rake
Esto ejecutará las pruebas (rspec y pepino), rubocop y se apresurará a sí mismo.
Otra tarea de rastrillo útil es la tarea console . Esto te arrojará directamente a un entorno donde puedes jugar con módulos y clases de reeks:
bundle exec rake console
irb(main):001> Reek::Examiner
=> Reek::Examiner
También puede usar IRB mientras ejecuta las pruebas agregando lo siguiente en el punto en el que desea comenzar a depurar:
binding . irbEche un vistazo a nuestra API de desarrollador para obtener más inspiración.
Desde entonces debes ver:
Si no tiene ganas de ensuciarse las manos con código, todavía hay otras formas en que puede ayudarnos:
Si se encuentra con problemas de clima de código (por ejemplo, repasa el umbral de duplicación de código), es posible que desee poder ejecutar el clima de código contra la base de código REEK localmente. Para hacer esto, debe hacer lo siguiente:
gem install codeclimatecodeclimate engines:install Ahora puede ejecutar varios motores climáticos de código, por ejemplo, codeclimate analyze -e duplication
Reek admite 6 formatos de salida:
--format html )--format yaml , ver también informes Yaml)--format json )--format xml )--format github ) Hacer que Reek "Rails" sea bastante simple, ya que apoyamos configuraciones específicas de directorio ( directory directives en Reek Talk). Simplemente agregue esto a su archivo de configuración:
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 : falseSin embargo, tenga cuidado, Reek no fusiona sus entradas de configuración, por lo que si ya tiene una directiva de directorio para "APP/Controladores" o "APP/Ayudos", debe actualizar esas directivas en lugar de copiar la muestra YAML anterior en su archivo de configuración.
Una lista no exhaustiva de otros analizadores de código estático que quizás desee considerar:
El equipo de Reek Core consiste en:
El autor original de Reek es Kevin Rutherford.
El autor del logotipo de Reek es Sonja Heinen.
Las contribuciones notables vinieron de: