Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Checking Ruby Programs without Types

Checking Ruby Programs without Types

Tokyo Rubyist Meetup 2016-11-25
https://github.com/soutaro/querly

Soutaro Matsumoto

November 25, 2016
Tweet

More Decks by Soutaro Matsumoto

Other Decks in Programming

Transcript

  1. @soutaro • Worked for analysis of Ruby programs for PhD

    • Co-founded Ubiregi Inc.
 (left 2016) • Working for SideCI
  2. Querly • Pattern based Ruby program check tool • $

    gem install querly
 https://github.com/soutaro/querly • Sponsored by SideCI (Actcat)
  3. rules: - id: sample.update_all pattern: update_all message: update_all skips validations

    $ querly check . team.rb:10:4 team.members.update_all(…) update_all is … querly.yml class Team … team.members.update_all(food: :fish) zoo.update_alligator … team.rb
  4. Goal • Not on syntactic issues (LINT) • Not to

    prove correctness (Types, Theorem prover) Code Review Assistance on Semantics
  5. team.members.update_all(food: :fish) People.all.find_each do |member|
 UpdatePersonJob.perform_later(member)
 end • Using 30x

    faster UpdatePeopleJob looks better • Is it safe to skip validation and callbacks? • Is iterating all people too slow?
  6. • LINT tool for project specific rules • Encourages users

    to add their custom rules • Define rules by simple pattern, not by Ruby
  7. Using Receiver JSON.parse • YAML.parse(source) • x.parse(source) • parse(source) •

    JSON.parse(src) • JSON.parse(src, symbolize_names: false) Match No Match
  8. Using Keyword save(validate: false) • record.save(validate: true) • record.save() •

    record.save(validate: !skip) • record.save(validate: false)
  9. Using Keyword self.string(:symbol:, !null: _, ...) • string :name, null:

    true • string :name, null: false • string :name • string :name, encoding: :utf8mb4
  10. Using Context save [!conditional] • record.save • result = record.save


    … if result • … unless record.save • record.save or return
  11. Workflow Assumption • Run Querly on CI, when Pull Request

    is open • Filter warnings based on diff
  12. Working with Querly 1. Find bad program pattern 2. Add

    rules for the pattern 3. Run Querly 4. Fix code or ignore warning
  13. Code Review Automation id: com.assert_selector_without_count pattern: "assert_selector(..., !count: _, ...)"

    message: Specify count: option when you are using assert_selector assert_selector “div.category-name”
  14. Share Best Practice id: sample.order pattern: “order(:string:)” message: Use order(key:

    :desc) form for descending order account.customers.order(“last_visited_at DESC”)
  15. Admit Bad Code • We have recently introduced caching of

    account’s attributes, but could not find good way to discard caches on reload • This is not very good implementation but we want to accept the change because existing code works fine • What happen for new code in the future? - id: sample.account.reload pattern: - account.reload - @account.reload - accounts.reload message: | Reloading account object does not discard cached values
  16. Deleting Monkey Patches • Stop defining monkey patch to add

    blank alt when not specified - id: sample.image_tag pattern: “image_tag(..., !alt:_, ...)” message: Specify alt attribute; a blank string?
  17. Conclusion • Querly helps your code review
 https://github.com/soutaro/querly • Experiment

    for checking programs without advanced program analysis (types)