
Оглавление

Reek - это инструмент, который изучает классы Ruby, модули и методы и отчеты о любых пахках кода, которые он находит.
Для отличного знакомства с кодовыми запахами и повторения, ознакомьтесь с этим сообщением в блоге или в этом. Есть также этот разговор от Rubyconfby (есть также слайд -колода, если вы предпочитаете).
Установите его через Rubygems:
gem install reekИ запустите это так:
reek [options] [dir_or_source_file] * Представьте себе, что исходный файл demo.rb содержащий:
# Smelly class
class Smelly
# This will reek of UncommunicativeMethodName
def x
y = 10 # This will reek of UncommunicativeVariableName
end
endReek сообщит о следующем запахе кода в этом файле:
$ 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 официально поддерживается для Cruby от 3,0 до 3.3 и для Jruby 9.4. Другие реализации Ruby (например, Rubinius) официально не поддерживаются, но также должны работать.
Обратите внимание, что в каждой версии Ruby Reek будет использовать анализатор для этой версии Ruby. Таким образом, вы всегда должны запускаться, используя одну из целевых версий вашего проекта Ruby.
Reek фокусируется на запахах кода высокого уровня, поэтому мы не можем сказать вам, как исправить предупреждения в общем виде; Это и всегда будет полностью зависеть от вашего доменного языка и бизнес -логики.
Тем не менее, пример может помочь вам начать. Взгляните на этот образец модели Ruby on Rails (имейте в виду, что это усечено, а не рабочий код):
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
endЗапуск REEK в этом файле так:
reek app/models/shopping_cart.rb
сообщит:
[5, 5]:ShoppingCart#gross_price refers to item more than self (FeatureEnvy)
Исправить это довольно просто. Поместите расчет валовой цены для одного предмета, где он принадлежит, что будет классом 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
endКод запах документов может дать вам дальнейшие намеки - обязательно ознакомьтесь с тем, что у вас есть предупреждение, с которым вы не знаете, как иметь дело.
Есть несколько способов, которыми вы можете провести работу над источниками, самое распространенное.
reek lib/Если вы не передаете никаких аргументов источника, чтобы оборотнее, это просто принимает текущий рабочий каталог в качестве источника.
Так
reekТо же самое, что явное:
reek .Кроме того
echo " class C; def m; end; end " | reekЭто распечатало бы:
$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 включает в себя проверки на некоторые аспекты управляющей пары, сцепления данных, зависть к функции, большой класс, дальний список параметров, моделируемый полиморфизм, слишком много утверждений, бессмысленное имя, неиспользованные параметры и многое другое. Смотрите код пахнет для актуальных подробностей о том, что REEK проверит в вашем коде.
Специальная конфигурация для спорных детекторов:
Неиспользованный частный метод отключен по умолчанию, потому что он довольно спорный, что означает, что вы должны явно активировать его в своей конфигурации через
UnusedPrivateMethod :
enabled : trueФункция полезности - это спорный детектор, который может оказаться действительно неумолимым. Как следствие, мы позволили отключить его для непубличных методов, подобных этим:
---
UtilityFunction :
public_methods_only : true Для базового обзора, запустите
reek -- helpКраткое описание этих параметров CLI см. Параметры командной строки.
Настройка REEK через файл конфигурации является наиболее мощным способом. Reek ожидает, что это имя файла будет .reek.yml , но вы можете переопределить это через переключатель CLI -c (см. Ниже).
Есть три способа передачи файла конфигурации:
-c (см. Интерфейс командной строки выше)Порядок, в котором Reek пытается найти такой файл конфигурации, точно выше: сначала он проверяет, если мы дали ему файл конфигурации явно через CLI; Затем он проверяет текущий рабочий каталог для файла и, если он не может его найти, он пересекает каталоги, пока не попадет в корневую каталог; Наконец, он проверяет ваш домашний каталог.
Как только Reek обнаруживает файл конфигурации, он немедленно перестает искать, а это означает, что с точки зрения Reek существует ровно один файл конфигурации и одну конфигурацию, независимо от того, сколько *.reek File у вас может быть в вашей файловой системе.
Мы прилагаем много усилий для создания конфигурации Reek как можно более пояснительной, поэтому лучший способ понять это - просмотреть простой пример (например, .reek.yml в вашем каталоге проекта):
---
# ## 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.rbКак вы видите выше, конфигурация Reek состоит из 3 различных разделов, обозначаемых 3 разными ключами:
Все, что вы добавите в свою конфигурацию, должно быть охвачено под одним из этих ключей.
Если у вас есть директива каталогов, для которой существует директива по умолчанию, более конкретная (которая является директивой каталога) будет иметь приоритет.
Эта конфигурация, например:
---
detectors :
IrresponsibleModule :
enabled : false
TooManyStatements :
max_statements : 5
directories :
" app/controllers " :
TooManyStatements :
max_statements : 10переводится на:
Каждый детектор запаха поддерживает наши основные варианты запаха. Как вы можете видеть выше, определенные типы запахов предлагают конфигурацию, которая выходит за рамки основных вариантов запаха, например, комки данных. Все варианты, которые выходят за рамки основных вариантов запаха, задокументированы на соответствующей странице типа запаха /DOCS (если вы хотите получить быстрый обзор всех возможных конфигураций, вы также можете проверить файл defaults.reek.yml в этом хранилище.
Обратите внимание, что вам вообще не нужен файл конфигурации. Если у вас все в порядке со всеми нами по умолчанию, вы можете полностью пропустить это.
Не беспокойтесь о том, чтобы ввести ошибку в вашем файле конфигурации, которая может остаться незамеченной - REEK использует схему для проверки вашей конфигурации против запуска и будет громко провалиться на случай, если вы списали на опцию или использовали неправильный тип данных для такого значения, как это:
Error: We found some problems with your configuration file: [/detectors/DetectorWithTypo] key 'DetectorWithTypo:' is undefined.
REEK принимает один файл конфигурации и один файл конфигурации только с помощью .reek.yml - имя по умолчанию.
В случае, если вам нужно иметь один или несколько файлов конфигурации в каталоге (например, вы играете с различными взаимоисключающими настройками), вам нужно явно сообщить REEK, какой файл использовать через reek -c config.reek .
Если вам нужно подавить предупреждение о запахе, и вы не можете или не хотите использовать файлы конфигурации по любым причинам, которые вы также можете использовать специальные комментарии исходного кода, такие как это:
# This method smells of :reek:NestedIterators
def smelly_method foo
foo . each { | bar | bar . each { | baz | baz . qux } }
endВы даже можете передать настройки конкретных настройки запаха:
# :reek:NestedIterators { max_allowed_nesting: 2 }
def smelly_method foo
foo . each { | bar | bar . each { | baz | baz . qux } }
endЭто невероятно мощная особенность и дополнительно объясняется под подавлением запаха.
Благодаря DEKEKS Dynamic Mechanism поиска файла конфигурации вы можете столкнуться с ситуацией, когда вы не уверены на 100%, какой File Configuration File использует. Например, у вас есть файл конфигурации, специфичный для проекта, в корне проекта, а также еще одна конфигурация REEK в вашем домашнем каталоге, который вы используете для всех других ваших проектов, и по любым причинам REEK, кажется, использует другой файл конфигурации, чем тот, который, как вы предполагали, это будет.
В этом случае вы можете передавать флаг --show-configuration-path , который приведет к тому, что REEK выводит путь в файл конфигурации, который он использует.
Интеграция таких инструментов, как REEK в существующую более крупную кодовую базу, может быть пугающей, когда вам нужно сначала исправить, возможно, сотни или тысячи предупреждений о запахах. Конечно, вы можете вручную отключить предупреждения о запахе, как показано выше, но в зависимости от размера вашей кодовой базы это может быть не вариант. К счастью, Reek предоставляет флаг «todo», который вы можете использовать для создания конфигурации, которая подаст все предупреждения о запахе для текущей кодовой базы:
reek --todo lib/Это создаст файл '.reek.yml' в вашем текущем рабочем каталоге.
Затем вы можете использовать это в качестве своей конфигурации - поскольку ваш рабочий каталог, вероятно, является корнем проекта в большинстве случаев, вам не нужно явно сообщать Reek. См. Загрузка конфигурации выше.
Если по каким -либо причинам вы решите поместить «.reek.yml» куда -то еще, где Рик не займет его автоматически, вам нужно явно сказать Reek, чтобы сделать это через:
reek -c whatever/.reek.yml lib/ Важно понимать, что пример использования номер один из флага --todo должен быть запущен один раз в начале введения Deek, чтобы облегчить переход. Если вы обнаружите, что хотите повторно разобраться с флагом --todo , чтобы заставить замолчать много новых предупреждений, вы победите цель как --todo , так и самого Deek.
Как следствие, запуск Reek с флагом --todo снова не будет перезаписать существующее '.reek.yml' и вместо этого прервать исполнение. Это также не будет принимать никаких других файлов конфигурации, который вы могли бы учесть.
Это означает, что когда вы бежите
reek -c other_configuration.reek --todo lib/ other_configuration.reek будет просто игнорируется.
Конечно, вы всегда можете просто удалить существующий файл .reek.yml, а затем запустить Reek с помощью флага --todo но имейте в виду, что это не предполагаемый случай использования этой функции.
Помимо очевидного
reek [options] [dir_or_source_file] *Есть довольно много других способов, как использовать REEK в ваших проектах:
Первое, что вы хотите сделать после проверки исходного кода, - это запустить Bundler:
bundle install
а затем запустите тесты:
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 23Или просто запустите весь набор тестирования:
bundle exec rake
Это запустит тесты (Rspec и огурец), Rubocop и сам.
Еще одна полезная задача грабли - задача console . Это бросит вас прямо в среду, в которой вы можете поиграть с модулями и классами Reeks:
bundle exec rake console
irb(main):001> Reek::Examiner
=> Reek::Examiner
Вы также можете использовать IRB при выполнении тестов, добавив следующее в той точке, где вы хотите начать отладку:
binding . irbПосмотрите на наш разработчик API для большего вдохновения.
С тех пор вы должны проверить:
Если вам не хочется испачкать руки с помощью кода, вы можете нам помочь:
Если вы столкнетесь с проблемами климата кода (например, перейдите по порогу дублирования кода), вы можете иметь возможность запустить Code Climate по сравнению с кодовой базой Deek. Для этого вам нужно сделать следующее:
gem install codeclimatecodeclimate engines:install Теперь вы можете запустить различные кодовые климатические двигатели, например, codeclimate analyze -e duplication
Reek поддерживает 6 выходных форматов:
--format html )--format yaml , см. Также отчеты Yaml)--format json )--format xml )--format github ) Создание Reek «Rails»-дружеские, довольно просты, поскольку мы поддерживаем специфические конфигурации каталогов ( directory directives в Reek Talk). Просто добавьте это в свой файл конфигурации:
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 : falseБудьте осторожны, REEK не объединяет ваши записи на конфигурацию, поэтому, если у вас уже есть директива каталогов для «приложения/контроллеров» или «приложения/помощники», вам нужно обновить эти директивы вместо копирования вышеуказанного образца YAML в файл конфигурации.
Неэпхарактивный список других анализаторов статического кода, которые вы, возможно, захотите изучить:
Команда Reek Core состоит из:
Первоначальный автор Reek - Кевин Резерфорд.
Автор логотипа Рика - Соня Хейнен.
Примечательные вклад пришли из: