
สารบัญ

Reek เป็นเครื่องมือที่ตรวจสอบคลาสทับทิมโมดูลและวิธีการและรายงานรหัสใด ๆ ที่พบ
สำหรับการแนะนำที่ยอดเยี่ยมเกี่ยวกับรหัสกลิ่นและ reek ลองดูโพสต์บล็อกนี้หรือที่ นอกจากนี้ยังมีการพูดคุยนี้จาก 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 การใช้งานทับทิมอื่น ๆ (เช่น Rubinius) ไม่ได้รับการสนับสนุนอย่างเป็นทางการ แต่ควรใช้งานได้เช่นกัน
โปรดทราบว่าในแต่ละรุ่นทับทิม Reek จะใช้ตัวแยกวิเคราะห์สำหรับทับทิมเวอร์ชันนั้น ดังนั้นคุณควรใช้ REEK โดยใช้หนึ่งในรุ่นทับทิมเป้าหมายของโครงการของคุณ
Reek มุ่งเน้นไปที่กลิ่นโค้ดระดับสูงดังนั้นเราจึงไม่สามารถบอกคุณถึงวิธีแก้ไขคำเตือนในแบบทั่วไป นี่คือและจะขึ้นอยู่กับภาษาโดเมนและตรรกะทางธุรกิจของคุณเสมอ
ที่กล่าวว่าตัวอย่างอาจช่วยให้คุณไปได้ ดูตัวอย่างของโมเดลทับทิมบนราง (โปรดทราบว่าสิ่งนี้ถูกตัดทอนไม่ใช่รหัสทำงาน):
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เป็นสิ่งที่แน่นอนว่าเป็นที่ชัดเจน:
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 รวมถึงการตรวจสอบบางแง่มุมของคู่ควบคุม, กอข้อมูล, ความอิจฉาคุณลักษณะ, คลาสขนาดใหญ่, รายการพารามิเตอร์ยาว, polymorphism จำลอง, ข้อความมากเกินไป, ชื่อที่ไม่ได้ใช้, พารามิเตอร์ที่ไม่ได้ใช้และอื่น ๆ ดูรหัสกลิ่นสำหรับรายละเอียดล่าสุดของสิ่งที่ Reek จะตรวจสอบในรหัสของคุณ
การกำหนดค่าพิเศษสำหรับเครื่องตรวจจับการโต้เถียง:
วิธีการส่วนตัวที่ไม่ได้ใช้ถูกปิดใช้งานโดยค่าเริ่มต้นเนื่องจากเป็นความขัดแย้งซึ่งหมายความว่าคุณต้องเปิดใช้งานอย่างชัดเจนในการกำหนดค่าของคุณผ่าน
UnusedPrivateMethod :
enabled : trueฟังก์ชั่นยูทิลิตี้เป็นเครื่องตรวจจับการโต้เถียงเช่นกันที่สามารถกลายเป็นสิ่งที่ไม่ได้ให้อภัยจริงๆ ด้วยเหตุนี้เราจึงทำให้สามารถปิดการใช้งานได้สำหรับวิธีการที่ไม่ใช่แบบสาธารณะเช่นนี้:
---
UtilityFunction :
public_methods_only : true สำหรับภาพรวมพื้นฐาน Run
reek -- helpสำหรับบทสรุปของตัวเลือก CLI เหล่านั้นดูตัวเลือกบรรทัดคำสั่ง
การกำหนดค่า Reek ผ่านไฟล์กำหนดค่าเป็นวิธีที่ทรงพลังที่สุด Reek คาดว่าชื่อไฟล์นี้จะเป็น .reek.yml แต่คุณสามารถแทนที่สิ่งนี้ผ่านสวิตช์ CLI -c (ดูด้านล่าง)
มีสามวิธีในการส่งผ่านไฟล์การกำหนดค่า:
-c (ดู อินเทอร์เฟซบรรทัดคำสั่ง ด้านบน)ลำดับที่ Reek พยายามค้นหาไฟล์การกำหนดค่าดังกล่าวเป็นไปตามนั้น: ก่อนอื่นจะตรวจสอบว่าเราได้ให้ไฟล์การกำหนดค่าอย่างชัดเจนผ่าน CLI; จากนั้นจะตรวจสอบไดเรกทอรีการทำงานปัจจุบันสำหรับไฟล์และหากไม่พบไฟล์หนึ่งมันจะผ่านไดเรกทอรีจนกว่าจะถึงไดเรกทอรีราก สุดท้ายมันตรวจสอบไดเรกทอรีบ้านของคุณ
ทันทีที่ Reek ตรวจพบไฟล์การกำหนดค่ามันจะหยุดการค้นหาทันทีซึ่งหมายความว่าจากมุมมองของ Reek มีไฟล์การกำหนดค่าหนึ่งไฟล์และการกำหนดค่าหนึ่งรายการโดยไม่คำนึงถึงจำนวนไฟล์ *.reek ที่คุณอาจมีในระบบไฟล์ของคุณ
เราใช้ความพยายามอย่างมากในการกำหนดค่าของ 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แปลเป็น:
เครื่องตรวจจับกลิ่นทุกตัวรองรับตัวเลือกกลิ่นขั้นพื้นฐานของเรา ดังที่คุณเห็นด้านบนประเภทกลิ่นบางชนิดมีการกำหนดค่าที่นอกเหนือไปจากตัวเลือกกลิ่นพื้นฐานเช่นกลุ่มข้อมูล ตัวเลือกทั้งหมดที่เกินกว่าตัวเลือกกลิ่นขั้นพื้นฐานจะถูกบันทึกไว้ในหน้าประเภทกลิ่น /เอกสารที่สอดคล้องกัน (หากคุณต้องการรับภาพรวมอย่างรวดเร็วจากการกำหนดค่าที่เป็นไปได้ทั้งหมดคุณสามารถตรวจสอบไฟล์ 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นี่เป็นคุณสมบัติที่ทรงพลังอย่างไม่น่าเชื่อและอธิบายเพิ่มเติมภายใต้การปราบปรามกลิ่น
ด้วยกลไก Dynamic ของ Reeks ในการค้นหาไฟล์การกำหนดค่าคุณอาจพบกับสถานการณ์ที่คุณไม่แน่ใจ 100% ว่าไฟล์การกำหนดค่าที่ Reek ใช้อยู่ เช่นคุณมีไฟล์การกำหนดค่าเฉพาะโครงการในรูทโครงการของคุณและการกำหนดค่า Reek อื่นในไดเรกทอรีโฮมไดเรกทอรีของคุณที่คุณใช้สำหรับโครงการอื่น ๆ ทั้งหมดของคุณและด้วยเหตุผลใดก็ตามที่ Reek ดูเหมือนจะใช้ไฟล์การกำหนดค่าอื่นกว่าที่คุณคิด
ในกรณีนี้คุณสามารถส่งธง --show-configuration-path ไปยัง Reek ซึ่งจะทำให้ Reek ส่งออกพา ธ ไปยังไฟล์การกำหนดค่าที่ใช้
การรวมเครื่องมือเช่น Reek เข้ากับ codebase ขนาดใหญ่ที่มีอยู่อาจเป็นเรื่องที่น่ากลัวเมื่อคุณต้องแก้ไขคำเตือนกลิ่นหลายร้อยหรือหลายพันครั้งก่อน แน่ใจว่าคุณสามารถปิดการใช้งานคำเตือนกลิ่นได้เช่นเดียวกับที่แสดงด้านบน แต่ขึ้นอยู่กับขนาดของ codebase ของคุณนี่อาจไม่ใช่ตัวเลือก โชคดีที่ Reek ให้ธง 'todo' ซึ่งคุณสามารถใช้เพื่อสร้างการกำหนดค่าที่จะระงับคำเตือนกลิ่นทั้งหมดสำหรับ codebase ปัจจุบัน:
reek --todo lib/สิ่งนี้จะสร้างไฟล์ '.reek.yml' ในไดเรกทอรีการทำงานปัจจุบันของคุณ
จากนั้นคุณสามารถใช้สิ่งนี้เป็นการกำหนดค่าของคุณ - เนื่องจากไดเรกทอรีการทำงานของคุณอาจเป็นรูทโครงการของคุณในกรณีส่วนใหญ่คุณไม่จำเป็นต้องบอก Reek อย่างชัดเจนเพื่อใช้ '.reek.yml' เพราะ Reek จะหยิบมันขึ้นมาโดยอัตโนมัติและใช้เป็นไฟล์กำหนดค่า ดูการโหลดการกำหนดค่าด้านบน
หากด้วยเหตุผลใดก็ตามที่คุณตัดสินใจที่จะใส่ '.reek.yml' ที่อื่นที่ Reek จะไม่หยิบมันขึ้นมาโดยอัตโนมัติคุณต้องบอก Reek อย่างชัดเจนว่าจะทำเช่นนั้นผ่าน:
reek -c whatever/.reek.yml lib/ เป็นสิ่งสำคัญที่จะต้องเข้าใจว่ากรณีการใช้งานอันดับหนึ่งของ --todo Flag นั้นจะต้องดำเนินการหนึ่งครั้งในตอนต้นของการแนะนำของ Reek เพื่อลดการเปลี่ยนแปลง หากคุณพบว่าตัวเองต้องการที่จะเรียกใช้ Reek อีกครั้งด้วยธง --todo เพื่อปิดปากคำเตือนใหม่จำนวนมากที่คุณเอาชนะจุดประสงค์ของทั้งธง --todo และรีคเอง
เป็นผลให้การรัน Reek ด้วย --todo Flag อีกครั้งจะไม่เขียนทับ '.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 และ Reek เอง
งานเรคที่มีประโยชน์อีกอย่างหนึ่งคืองาน console สิ่งนี้จะทำให้คุณเข้าสู่สภาพแวดล้อมที่คุณสามารถเล่นกับโมดูลและชั้นเรียนของ Reeks:
bundle exec rake console
irb(main):001> Reek::Examiner
=> Reek::Examiner
นอกจากนี้คุณยังสามารถใช้ IRB ในขณะที่เรียกใช้การทดสอบโดยเพิ่มสิ่งต่อไปนี้ ณ จุดที่คุณต้องการเริ่มการดีบัก:
binding . irbดู API นักพัฒนาของเราเพื่อหาแรงบันดาลใจเพิ่มเติม
จากนั้นคุณควรตรวจสอบ:
หากคุณไม่รู้สึกว่ามือของคุณสกปรกด้วยรหัสยังมีวิธีอื่นที่คุณสามารถช่วยเราได้:
หากคุณพบปัญหาเกี่ยวกับสภาพภูมิอากาศของรหัส (เช่นไปที่เกณฑ์การทำซ้ำรหัส) คุณอาจต้องการเรียกใช้ Code Climate กับ Reek Codebase ในเครื่อง ในการทำเช่นนี้คุณต้องทำสิ่งต่อไปนี้:
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 ข้างต้นลงในไฟล์การกำหนดค่าของคุณ
รายการเครื่องวิเคราะห์รหัสสแตติกอื่น ๆ ที่ไม่ครบถ้วนสมบูรณ์ที่คุณอาจต้องการดู:
ทีม Core ของ Reek ประกอบด้วย:
ผู้เขียนดั้งเดิมของ Reek คือ Kevin Rutherford
ผู้เขียนโลโก้ของ Reek คือ Sonja Heinen
การมีส่วนร่วมที่โดดเด่นมาจาก: