
Table des matières

Reek est un outil qui examine les classes, les modules et les méthodes de Ruby et rapporte que toutes les odeurs de code qu'il trouve.
Pour une excellente introduction aux odeurs de code et Reek, consultez cet article de blog ou celui-là. Il y a aussi cette conversation de RumbyConfby (il y a aussi un jeu de diapositives si vous préférez cela).
Installez-le via Rubygems:
gem install reekEt exécutez-le comme ceci:
reek [options] [dir_or_source_file] * Imaginez un fichier source demo.rb contenant:
# Smelly class
class Smelly
# This will reek of UncommunicativeMethodName
def x
y = 10 # This will reek of UncommunicativeVariableName
end
endReek rapportera les odeurs de code suivantes dans ce fichier:
$ 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 est officiellement soutenu pour CRUBY 3.0 à 3.3 et pour JRuby 9.4. D'autres implémentations Ruby (comme Rubinius) ne sont pas officiellement soutenues mais devraient également fonctionner.
Notez que, sur chaque version Ruby, Reek utilisera l'analyseur pour cette version de Ruby. Ainsi, vous devez toujours exécuter Reek en utilisant l'une des versions Ruby cibles de votre projet.
Reek se concentre sur les odeurs de code de haut niveau, nous ne pouvons donc pas vous dire comment réparer les avertissements de manière générique; Ceci est et dépendra toujours complètement de votre langue de domaine et de votre logique métier.
Cela dit, un exemple pourrait vous aider à y aller. Jetez un œil à cet échantillon d'un modèle Ruby on Rails (sachez que cela est tronqué, pas de code de travail):
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
endExécuter Reek sur ce fichier comme ceci:
reek app/models/shopping_cart.rb
Rapporterait:
[5, 5]:ShoppingCart#gross_price refers to item more than self (FeatureEnvy)
Réparer ceci est assez simple. Mettez le calcul des prix bruts pour un seul élément où il appartient, qui serait la 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
endLe code sent les documents que les documents peuvent vous donner d'autres conseils - assurez-vous de les consulter d'abord lorsque vous avez un avertissement que vous ne savez pas comment gérer.
Il existe plusieurs façons dont vous pouvez avoir un travail sur les sources, la plus courante étant juste
reek lib/Si vous ne transmettez aucun argument source pour refuser, il faut simplement le répertoire de travail actuel comme source.
Donc
reekest exactement la même chose que d'être explicite:
reek .De plus, vous pouvez tuer le code pour recommencer comme ceci:
echo " class C; def m; end; end " | reekCela imprimerait:
$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 inclut actuellement des vérifications de certains aspects du couple de contrôle, de la toump de données, de l'envie des fonctionnalités, de la grande classe, de la liste des paramètres longs, du polymorphisme simulé, trop de déclarations, un nom peu communicatif, des paramètres inutilisés et plus encore. Voir les odeurs du code pour les détails à jour de ce que Reek vérifiera votre code.
Configuration spéciale pour les détecteurs controversés:
La méthode privée inutilisée est désactivée par défaut car elle est en quelque sorte controversée, ce qui signifie que vous devez l'activer explicitement dans votre configuration via
UnusedPrivateMethod :
enabled : trueLa fonction d'utilité est également un détecteur controversé qui peut s'avérer vraiment impitoyable. En conséquence, nous avons permis de le désactiver pour des méthodes non publiques comme celle-ci:
---
UtilityFunction :
public_methods_only : true Pour un aperçu de base, exécutez
reek -- helpPour un résumé de ces options CLI, voir les options de ligne de commande.
La configuration de Reek via un fichier de configuration est de loin la manière la plus puissante. Reek s'attend à ce que ce nom de fichier soit .reek.yml mais vous pouvez remplacer cela via le commutateur CLI -c (voir ci-dessous).
Il existe trois façons de passer à Reek le fichier de configuration:
-c (voir l'interface de ligne de commande ci-dessus)L'ordre dans lequel Reek essaie de trouver un tel fichier de configuration est exactement ce qui précède: il vérifie d'abord si nous lui avons donné un fichier de configuration explicitement via CLI; Ensuite, il vérifie le répertoire de travail actuel d'un fichier et s'il n'en trouve pas, il traverse les répertoires jusqu'à ce qu'il n'atteigne le répertoire racine; Enfin, il vérifie votre répertoire domestique.
Dès que Reek détecte un fichier de configuration, il cesse de rechercher immédiatement, ce qui signifie que du point de vue de Reek, il existe exactement un fichier de configuration et une configuration, quel que soit le nombre de fichiers *.reek que vous pourriez avoir sur votre système de fichiers.
Nous mettons beaucoup d'efforts pour rendre la configuration de Reek aussi explicite que possible, donc la meilleure façon de le comprendre est de regarder un exemple simple (par exemple .reek.yml dans votre répertoire de projet):
---
# ## 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.rbComme vous le voyez ci-dessus, la configuration de Reek se compose de 3 sections différentes indiquées par 3 clés différentes:
Tout ce que vous ajoutez à votre configuration doit être portée sous l'une de ces clés.
Si vous avez une directive de répertoire pour laquelle une directive par défaut existe, la plus spécifique (qui est la directive de répertoire) auront la priorité.
Cette configuration par exemple:
---
detectors :
IrresponsibleModule :
enabled : false
TooManyStatements :
max_statements : 5
directories :
" app/controllers " :
TooManyStatements :
max_statements : 10se traduit par:
Chaque détecteur d'odeur soutient nos options de base. Comme vous pouvez le voir ci-dessus, certains types d'odeur offrent une configuration qui va au-delà de celle des options de base, par exemple, la touffe de données. Toutes les options qui vont au-delà des options d'odeur de base sont documentées dans la page de type / document d'odeur correspondant (si vous souhaitez obtenir un aperçu rapide sur toutes les configurations possibles, vous pouvez également consulter le fichier defaults.reek.yml dans ce référentiel.
Notez que vous n'avez pas du tout besoin d'un fichier de configuration. Si vous êtes d'accord avec toutes les valeurs par défaut que nous définissons, vous pouvez le sauter complètement.
Ne vous inquiétez pas d'introduire une erreur dans votre fichier de configuration qui pourrait passer inaperçu - Reek utilise un schéma pour valider votre configuration contre le démarrage et échouera à haute voix au cas où vous auriez mal orthographié une option ou utilisé le mauvais type de données pour une valeur comme celle-ci:
Error: We found some problems with your configuration file: [/detectors/DetectorWithTypo] key 'DetectorWithTypo:' is undefined.
Reek prend un fichier de configuration et un fichier de configuration uniquement avec .reek.yml étant le nom par défaut.
Dans le cas où vous devez avoir un ou plusieurs fichiers de configuration dans le répertoire (par exemple, vous jouez avec différents paramètres mutuellement exclusifs), vous devez dire explicitement à Reek quel fichier utiliser via reek -c config.reek .
Dans le cas où vous devez supprimer un avertissement de l'odeur et que vous ne pouvez pas ou ne souhaitez pas utiliser des fichiers de configuration pour les raisons pour lesquelles vous pouvez également utiliser des commentaires de code source spécial comme celui-ci:
# This method smells of :reek:NestedIterators
def smelly_method foo
foo . each { | bar | bar . each { | baz | baz . qux } }
endVous pouvez même passer des paramètres de configuration spécifiques à l'odeur:
# :reek:NestedIterators { max_allowed_nesting: 2 }
def smelly_method foo
foo . each { | bar | bar . each { | baz | baz . qux } }
endIl s'agit d'une caractéristique incroyablement puissante et expliquée davantage sous la suppression des odeurs.
Avec le mécanisme dynamique des bornes de recherche d'un fichier de configuration, vous pourriez avoir une situation où vous n'êtes pas sûr à 100% quel fichier de configuration Reek utilise. Par exemple, vous avez un fichier de configuration spécifique à un projet dans la racine de votre projet et également une autre configuration Reek dans votre répertoire domestique que vous utilisez pour tous vos autres projets et pour toutes les raisons, Reek semble utiliser un autre fichier de configuration que celui que vous supposiez.
Dans ce cas, vous pouvez transmettre le Flag --show-configuration-path pour reek, ce qui fera en sorte que Reek puisse sortir le chemin d'accès au fichier de configuration qu'il utilise.
L'intégration d'outils comme Reek dans une base de code plus grande existante peut être intimidant lorsque vous devez d'abord réparer des centaines ou des milliers d'avertissements d'odeur. Bien sûr, vous pouvez désactiver manuellement les avertissements d'odeur comme indiqué ci-dessus, mais selon la taille de votre base de code, ce n'est peut-être pas une option. Heureusement, Reek fournit un drapeau «TODO» que vous pouvez utiliser pour générer une configuration qui supprimera tous les avertissements d'odeur pour la base de code actuelle:
reek --todo lib/Cela créera le fichier '.reek.yml' dans votre répertoire de travail actuel.
Vous pouvez ensuite l'utiliser comme votre configuration - car votre répertoire de travail est probablement votre racine de projet dans la plupart des cas, vous n'avez pas à dire explicitement à Reek d'utiliser '.rek.yml' parce que Reek le ramassera automatiquement et l'utilisera comme fichier de configuration. Voir le chargement de configuration ci-dessus.
Si pour une raison quelconque, vous décidez de mettre «.reek.yml» ailleurs où Reek ne le ramassera pas automatiquement, vous devez dire explicitement à Reek de le faire via:
reek -c whatever/.reek.yml lib/ Il est important de comprendre que le cas d'utilisation numéro un de l'indicateur --todo Todo doit être exécuté une fois au début de l'introduction de Reek pour faciliter la transition. Si vous vous retrouvez à vouloir réécouter Reek avec le drapeau --todo afin de faire taire de nombreux nouveaux avertissements, vous battez le but du drapeau --todo Todo et de Reek lui-même.
En conséquence, l'exécution de Reek avec le drapeau --todo ne remplacera pas une «.rek.yml» existante et abandonnera à la place l'exécution. Il ne prendra pas non plus d' autre fichier de configuration que vous pourriez avoir en compte.
Cela signifie que lorsque vous courez
reek -c other_configuration.reek --todo lib/ other_configuration.reek sera simplement ignoré.
Bien sûr, vous pouvez toujours supprimer le fichier .rek.yml existant, puis exécuter Reek avec l'indicateur --todo , mais gardez à l'esprit que ce n'est pas le cas d'utilisation prévu de cette fonctionnalité.
Outre l'évidence
reek [options] [dir_or_source_file] *Il existe plusieurs autres façons d'utiliser Reek dans vos projets:
La première chose que vous voulez faire après avoir vérifié le code source est d'exécuter Bundler:
bundle install
puis exécutez les tests:
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 exécutez tout simplement la suite de tests:
bundle exec rake
Cela exécutera les tests (RSPEC et Cucumber), Rubop et Reek lui-même.
Une autre tâche de Rake utile est la tâche console . Cela vous jettera directement dans un environnement où vous pourrez jouer avec des modules et des cours de boise:
bundle exec rake console
irb(main):001> Reek::Examiner
=> Reek::Examiner
Vous pouvez également utiliser la CISR lors de l'exécution des tests en ajoutant ce qui suit au point où vous souhaitez commencer à déboguer:
binding . irbJetez un œil à notre API développeur pour plus d'inspiration.
Depuis, vous devez vérifier:
Si vous n'avez pas envie de vous salir les mains avec du code, vous pouvez nous aider encore: vous pouvez nous aider:
Si vous rencontrez des problèmes climatiques de code (par exemple, passez en revue le seuil de duplication de code), vous voudrez peut-être exécuter le climat de code à la base de code reek localement. Pour ce faire, vous devez faire ce qui suit:
gem install codeclimatecodeclimate engines:install Vous pouvez maintenant exécuter divers moteurs climatiques de code, par exemple, codeclimate analyze -e duplication
Reek prend en charge 6 formats de sortie:
--format html )--format yaml , voir aussi Yaml Reports)--format json )--format xml )--format github ) Faire des "rails" reek-amicaux est assez simple car nous prenons en charge les configurations spécifiques du répertoire ( directory directives dans Reek Talk). Ajoutez-le simplement à votre fichier de configuration:
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 : falseSoyez prudent cependant, Reek ne fusionne pas vos entrées de configuration, donc si vous avez déjà une directive de répertoire pour "App / Controllers" ou "App / Aiders", vous devez mettre à jour ces directives au lieu de copier l'échantillon YAML ci-dessus dans votre fichier de configuration.
Une liste non exhaustive des autres analyseurs de code statiques que vous voudrez peut-être examiner:
L'équipe de base de Reek est composée de:
L'auteur original de Reek est Kevin Rutherford.
L'auteur du logo de Reek est Sonja Heinen.
Les contributions notables proviennent de: