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

読みやすいコードとRubyらしいコード

kokuyouwind
November 03, 2019

 読みやすいコードとRubyらしいコード

富山Ruby会議01での登壇資料です。

Ruby未経験のエンジニア層が多めと聞いていて、かつ午前2番目の発表だったため、入門っぽい題材にしました。とはいえ経験者もいるので、よく聞く「Rubyらしい」とはどういうことなのかを分析的に考えてみる、という内容にしています。

kokuyouwind

November 03, 2019
Tweet

More Decks by kokuyouwind

Other Decks in Programming

Transcript

  1. ブロックを使う # これよりも file = File.open(path) # 前処理 file.read #

    やりたいこと file.close # 後処理 # こっちのほうがRuby らしい File.open(path) do |file| file.read # やりたいこと end 1 2 3 4 5 6 7 8 9
  2. for ⽂を使わない # これよりも for i in 1..10 do print

    i end # こっちのほうがRuby らしい(?) (1..10).each do |i| print i end 1 2 3 4 5 6 7 8 9
  3. for ⽂を使わない # これよりも for i in 1..10 do print

    'hello' end # こっちのほうがRuby らしい! 10.times do print 'hello' end 1 2 3 4 5 6 7 8 9
  4. for ⽂を使わない # これよりも arr = [1,2,3] for i in

    0...arr.length do arr[i] = arr[i] ** 2 end # こっちのほうがRuby らしい! arr.map do |i| i ** 2 end 1 2 3 4 5 6 7 8 9 10
  5. for ⽂を使わない # これよりも sum = 0 for i in

    1..10 do sum += i end # こっちのほうがRuby らしい (1..10).reduce(0) do |sum, i| sum + i end 1 2 3 4 5 6 7 8 9 10
  6. メタプログラミング # これよりも class Test def field1; @field1; end def

    field2; @field2; end end # こっちのほうがRuby らしい class Test attr_reader :field1, :field2 end 1 2 3 4 5 6 7 8 9 10
  7. メタプログラミング # これよりも…… class Test def set_status_hoge @status = :hoge

    end def set_status_fuga @status = :fuga end end 1 2 3 4 5 6 7 8 9 10
  8. メタプログラミング # こっちのほうがRuby らしい? class Test status_setter :hoge, :fuga def

    status_setter(*statuses) statuses.each do |status| define_method "set_status_#{status}" do @status = status end end end end 1 2 3 4 5 6 7 8 9 10 11 12
  9. Misoca の⽂書変換 class DocumentConversion < ActiveRecord::Base def self.source_document_of(document) find_by(converted_document: document)

    end def self.converted_document_of(document) find_by(source_document: document) end end class Invoice < ActiveRecord::Base # 請求書クラスは⽂書変換について知らない end 1 2 3 4 5 6 7 8 9 10 11 12 13
  10. 案1. 普通に関連を持たせる class DocumentConversion < ActiveRecord::Base belongs_to :source_document, polymorphic: true

    belongs_to :converted_document, polymorphic: true end class Invoice < ActiveRecord::Base # 中間テーブル( ⽂書変換) への関連 has_many :document_conversions, as: :converted_document # 変換元の⾒積書への関連 as_many :source_estimates, through: :document_conversio source: :source_document, source_type: 'Estimate' # 変換先の納品書への関連も同じ感じ end 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
  11. 案2. モジュールにまとめる class Invoice < ActiveRecord::Base # ⽂書変換できることを明示するが、詳細な実装はモジュールに隠す include DocumentConvertible::Invoice

    end module DocumentConvertible module Invoice has_many :document_conversions, as: :converted_docume as_many :source_estimates, through: :document_convers source: :source_document, source_type: 'Estimate' end module Estimate; ...; end module DeliverySlip; ...; end end 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
  12. 案3. メタプロで宣⾔的にする class Invoice < ActiveRecord::Base # ⾒積書から変換できる include DocumentConvertible::From[Estimate]

    # 納品書に変換できる include DocumentConvertible::To[DeliverySlip] end module DocumentConvertible module From module_function def [](*class_names) # 受け取ったクラスを変換元⽂書として参照するために # 必要な関連・メソッドなどを定義する end end # module To も同様に定義 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16