Static Code Analysis For Ruby

3,492
-1

Published on

This is my presentation on Shanghai on Rails at 3.20. It introduces static code analysis for ruby, tells you a pattern to analysis ruby code and gives you some examples that how rails_best_practices analysis rails codes.

Published in: Technology
0 Comments
9 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
3,492
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
60
Comments
0
Likes
9
Embeds 0
No embeds

No notes for slide

Static Code Analysis For Ruby

  1. 1. Static Code Analysis for Ruby Richard Huang E kohe www.ekohe.com Web Development & Graphic Design China Ruby on Rails Development - Rails Consulting - Rails Services - Merb - Offshore Web Development
  2. 2. 有没有对 Ruby 代码进行过静态分析? www.ekohe.com Web Development & Graphic Design China Ruby on Rails Development - Rails Consulting - Rails Services - Merb - Offshore Web Development
  3. 3. 案例 www.ekohe.com Web Development & Graphic Design China Ruby on Rails Development - Rails Consulting - Rails Services - Merb - Offshore Web Development
  4. 4. 有没有看过张文钿的演讲稿 Rails Best Practices ? http://www.slideshare.net/ihower/rails-best-practices www.ekohe.com Web Development & Graphic Design China Ruby on Rails Development - Rails Consulting - Rails Services - Merb - Offshore Web Development
  5. 5. 有没有使用过 rails_best_practices gem ? http://github.com/flyerhzm/rails_best_practices www.ekohe.com Web Development & Graphic Design China Ruby on Rails Development - Rails Consulting - Rails Services - Merb - Offshore Web Development
  6. 6. 静态分析 VS 动态分析 <ul><li>整体 VS 局部 </li></ul><ul><li>粗略 VS 精确 </li></ul>www.ekohe.com Web Development & Graphic Design China Ruby on Rails Development - Rails Consulting - Rails Services - Merb - Offshore Web Development
  7. 7. 静态分析什么? 源程序? www.ekohe.com Web Development & Graphic Design China Ruby on Rails Development - Rails Consulting - Rails Services - Merb - Offshore Web Development
  8. 8. 抽象语法树 (AST) <ul><li>a = b * c + b * c </li></ul>www.ekohe.com Web Development & Graphic Design China Ruby on Rails Development - Rails Consulting - Rails Services - Merb - Offshore Web Development assign a * + * b b c c
  9. 9. s-expression www.ekohe.com Web Development & Graphic Design China Ruby on Rails Development - Rails Consulting - Rails Services - Merb - Offshore Web Development s(:class, :Student, nil, s(:scope, s(:block, s(:call, nil, :attr_accessor, s(:arglist, s(:lit, :name)) ), s(:defn, :initialize, s(:args, :name), s(:scope, s(:block, s(:iasgn, :@name, s(:lvar, :name)) ) ) ) ))) class Student attr_accessor :name def initialize(name) @name = name end end
  10. 10. s-expression www.ekohe.com Web Development & Graphic Design China Ruby on Rails Development - Rails Consulting - Rails Services - Merb - Offshore Web Development s(:defn, :output, s(:args, :arg1, :arg2), s(:scope, s(:block, s(:if, s(:call, s(:lvar, :arg1), :==, s(:arglist, s(:str, &quot;hello&quot;)) ), s(:call, nil, :print, s(:arglist, s(:lvar, :arg1), s(:lvar, :arg2)) ), s(:call, nil, :print, s(:arglist, s(:lvar, :arg1)) ) ) ) ) ) def output(arg1, arg2) if arg1 == 'hello' print arg1, arg2 else print arg1 end end
  11. 11. s-expression 的特点 <ul><li>类树(继承数组) </li></ul><ul><li>结构清晰 </li></ul><ul><li>方便解析 </li></ul>www.ekohe.com Web Development & Graphic Design China Ruby on Rails Development - Rails Consulting - Rails Services - Merb - Offshore Web Development
  12. 12. 如何生成 s-expression www.ekohe.com Web Development & Graphic Design China Ruby on Rails Development - Rails Consulting - Rails Services - Merb - Offshore Web Development ruby 源代码 s-expression ruby_parser ruby2ruby
  13. 13. 如何解析 s-expression ? <ul><li>Visitor Pattern </li></ul><ul><li>优点: </li></ul><ul><ul><li>数据结构与访问类分离 </li></ul></ul><ul><ul><li>方便地增加访问类 </li></ul></ul><ul><li>缺点: </li></ul><ul><ul><li>增加数据类型很麻烦 </li></ul></ul><ul><ul><li>访问类只能处理当前结点 </li></ul></ul>www.ekohe.com Web Development & Graphic Design China Ruby on Rails Development - Rails Consulting - Rails Services - Merb - Offshore Web Development
  14. 14. rails_best_practices 是如何做静态代码分析的? www.ekohe.com Web Development & Graphic Design China Ruby on Rails Development - Rails Consulting - Rails Services - Merb - Offshore Web Development
  15. 15. rails_best_practices www.ekohe.com Web Development & Graphic Design China Ruby on Rails Development - Rails Consulting - Rails Services - Merb - Offshore Web Development rails_best_practices 结果输出 代码检查类 代码解析器 配置 源代码 5. 代码检查 2. 生成检查类集合 3. 分析源代码 4. 生成 s-expression 1. 读取配置 6. 显示检查结果
  16. 16. 代码解析 <ul><li>解析顺序 </li></ul>www.ekohe.com Web Development & Graphic Design China Ruby on Rails Development - Rails Consulting - Rails Services - Merb - Offshore Web Development model files migration files controller files helper files view files …… migration files
  17. 17. 代码解析 www.ekohe.com Web Development & Graphic Design China Ruby on Rails Development - Rails Consulting - Rails Services - Merb - Offshore Web Development erb files haml files ruby files src precompiled ruby_parser s-expression
  18. 18. 代码检查 www.ekohe.com Web Development & Graphic Design China Ruby on Rails Development - Rails Consulting - Rails Services - Merb - Offshore Web Development s-expression class defn call Check UseModelAssociationCheck MoveFinderToNamedScopeCheck if UseScopeAccessCheck LawOfDemeterCheck
  19. 19. 代码检查 <ul><li>Visitor Pattern 扩展 </li></ul><ul><ul><li>不仅关注结点的类型 </li></ul></ul><ul><ul><li>而且关注结点所在的文件 </li></ul></ul>www.ekohe.com Web Development & Graphic Design China Ruby on Rails Development - Rails Consulting - Rails Services - Merb - Offshore Web Development
  20. 20. rails_best_practices 做静态代码分析的 一些 思路 www.ekohe.com Web Development & Graphic Design China Ruby on Rails Development - Rails Consulting - Rails Services - Merb - Offshore Web Development
  21. 21. ReplaceInstanceVariableWithLocalVariableCheck <ul><li># app/views/posts/_post.html.erb </li></ul><ul><li><%= @post.title %> </li></ul><ul><li><%= @post.body %> </li></ul>www.ekohe.com Web Development & Graphic Design China Ruby on Rails Development - Rails Consulting - Rails Services - Merb - Offshore Web Development
  22. 22. ReplaceInstanceVariableWithLocalVariableCheck <ul><li># app/views/posts/_post.html.erb </li></ul><ul><li><%= @post.title %> </li></ul><ul><li>在 partial 文件中任何类型为 ivar 的结点 都违反 </li></ul>www.ekohe.com Web Development & Graphic Design China Ruby on Rails Development - Rails Consulting - Rails Services - Merb - Offshore Web Development ivar s(:call, s(:ivar, :@post), :title, s(:arglist))
  23. 23. MoveFinderToNamedScopeCheck <ul><li>class PostsController < ApplicationController </li></ul><ul><li>def index </li></ul><ul><li>@published_posts = Post.find(:all, :limit => 10, :order => ‘created_at desc’) </li></ul><ul><li>end </li></ul><ul><li>end </li></ul>www.ekohe.com Web Development & Graphic Design China Ruby on Rails Development - Rails Consulting - Rails Services - Merb - Offshore Web Development
  24. 24. MoveFinderToNamedScopeCheck <ul><li>Post.find(:all, :limit => 10, :order => ‘created_at desc’) </li></ul><ul><li>在 controller 文件中 find, all, first, last 方法带类型为 hash 的参数的都违反 </li></ul>www.ekohe.com Web Development & Graphic Design China Ruby on Rails Development - Rails Consulting - Rails Services - Merb - Offshore Web Development const find, all, first, last hash s(:call, s(:const, :Post), :find, s(:arglist, s(:lit, :all), s(:hash, s(:lit, :limit), s(:lit, 10), s(:lit, :order), s(:str, &quot;created_at desc&quot;)) ) )
  25. 25. AddModelVirtualAttributeCheck <ul><li>class UsersController < ApplicationController </li></ul><ul><li>def create </li></ul><ul><li>@user = User.new(params[:user]) </li></ul><ul><li>@user.first_name = params[:full_name].split(‘ ‘, 2).first </li></ul><ul><li>@user.last_name = params[:full_name].split(‘ ‘, 2).last </li></ul><ul><li>@user.save </li></ul><ul><li>end </li></ul><ul><li>end </li></ul>www.ekohe.com Web Development & Graphic Design China Ruby on Rails Development - Rails Consulting - Rails Services - Merb - Offshore Web Development
  26. 26. AddModelVirtualAttributeCheck <ul><li>@user.first_name = params[:full_name].split(‘ ‘, 2).first </li></ul><ul><li>attrassign </li></ul><ul><li>@user.last_name = params[:full_name].split(‘ ‘, 2).last </li></ul><ul><li>attrassign </li></ul><ul><li>@user.save </li></ul><ul><li>对于一个 variable ,如果接收到两条不同的赋值消息,但参数的 &quot; 首部分 &quot; 是相同的,那么它就违反 </li></ul>www.ekohe.com Web Development & Graphic Design China Ruby on Rails Development - Rails Consulting - Rails Services - Merb - Offshore Web Development mesage arguments whose message is [] mesage arguments whose message is []
  27. 27. LawOfDemeterCheck <ul><li>class Invoice < ActiveRecord::Base </li></ul><ul><li>belongs_to :user </li></ul><ul><li>end </li></ul><ul><li><%= @invoice.user.name %> </li></ul>www.ekohe.com Web Development & Graphic Design China Ruby on Rails Development - Rails Consulting - Rails Services - Merb - Offshore Web Development
  28. 28. LawOfDemeterCheck <ul><li>class Invoice < ActiveRecord::Base </li></ul><ul><li>belongs_to :user </li></ul><ul><li>end </li></ul><ul><li><%= @invoice.user.name %> </li></ul><ul><li>app/models/*.rb 必须首先被解析 </li></ul><ul><li>如果 variable 的名字和 model 的 class name 匹配,同时调用的消息名和 association 名字相同,则违反 </li></ul>www.ekohe.com Web Development & Graphic Design China Ruby on Rails Development - Rails Consulting - Rails Services - Merb - Offshore Web Development message class name association name
  29. 29. AlwaysAddDbIndexCheck <ul><li>class CreateComments < ActiveRecord::Migration </li></ul><ul><li>def self.up </li></ul><ul><li>create_table :comments do |t| </li></ul><ul><li>t.string :content </li></ul><ul><li>t.integer :post_id </li></ul><ul><li>t.integer :user_id </li></ul><ul><li>end </li></ul><ul><li>end </li></ul><ul><li>end </li></ul>www.ekohe.com Web Development & Graphic Design China Ruby on Rails Development - Rails Consulting - Rails Services - Merb - Offshore Web Development
  30. 30. AlwaysAddDbIndexCheck <ul><li>create_table :comments do |t| </li></ul><ul><li>t.string :content </li></ul><ul><li>t.integer :post_id </li></ul><ul><li>t.integer :user_id </li></ul><ul><li>end </li></ul><ul><li>add_index :comments, :post_id </li></ul><ul><li>db/migrations/*.rb 必须被解析两次 </li></ul><ul><li>所有 create_table 中创建的外键没有出现在 add_index 的参数中,那么它就违反 </li></ul>www.ekohe.com Web Development & Graphic Design China Ruby on Rails Development - Rails Consulting - Rails Services - Merb - Offshore Web Development table name integer with _id column with _id and integer references
  31. 31. AlwaysAddDbIndexCheck <ul><li>What about? </li></ul><ul><li>[[:comments, :post_id], [:comments, :user_id]].each do |args| </li></ul><ul><li>add_index *args </li></ul><ul><li>end </li></ul>www.ekohe.com Web Development & Graphic Design China Ruby on Rails Development - Rails Consulting - Rails Services - Merb - Offshore Web Development
  32. 32. AlwaysAddDbIndexCheck <ul><li>Ruby2Ruby.new.process(node) </li></ul><ul><li>模拟 add_index ,动态处理 </li></ul><ul><li>Ruby is Powerful! </li></ul>www.ekohe.com Web Development & Graphic Design China Ruby on Rails Development - Rails Consulting - Rails Services - Merb - Offshore Web Development def add_index(*args) table_name, column_names = *args table_name = table_name.to_s # call AlwaysAddDbIndexCheck method end
  33. 33. 静态代码分析 代码检查 代码重构 www.ekohe.com Web Development & Graphic Design China Ruby on Rails Development - Rails Consulting - Rails Services - Merb - Offshore Web Development
  34. 34. Q&A Thank you Website: http://www.huangzhimin.com Github: http://github.com/flyerhzm www.ekohe.com Web Development & Graphic Design China Ruby on Rails Development - Rails Consulting - Rails Services - Merb - Offshore Web Development
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×