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

Rails構成とオブジェクト指向/ rails-structure-and-object-oriented

26452e41a2eef1d9f05cea3f28802641?s=47 @amyroi
June 08, 2018
470

Rails構成とオブジェクト指向/ rails-structure-and-object-oriented

26452e41a2eef1d9f05cea3f28802641?s=128

@amyroi

June 08, 2018
Tweet

Transcript

  1. コード構成素案 主にビジネスロジックの話 @amyroi

  2. コード配置例 # 例 app/ ├ lib/ # もしくは lib/ 配下、autoload

    │ └ aiml/ # プロダクトコードに影響しないコンポーネン │ └ aws/ # プロダクトコードに影響しないコンポーネント │ └ nlu/ # gem 化想定 │ ├ models/ │ └ concerns/ # ActiveSupport::Concern │ └ user.rb # ActiveRelation 継承 │ └ validators/ # 独自validation クラス ├ behaviors/ │ └ user_search_form.rb # Form オブジェクト │ # | Service クラス │ # | Decorator クラス │ └ nlu_manage/ # プロジェクト内で行うNLU への │ # アクセス関するクラスをまとめるnamespace │ └ project.rb # 振る舞いのクラス │ └ bot.rb # 振る舞いのクラス 2
  3. 継承と結合をなくしていく module, callback, 継承の使用を極力さける 継承より委譲 密結合 → 疎結合へ lib配下のライブラリは対象外 3

  4. メリット 振る舞いに合わせたオブジェクト設計 疎結合にすることによりユニットテストの見通しがよくなる デメリット デザインパターンの乱用 振る舞いにおけるファイル数増 4

  5. 継承 class A def save end end class B <

    A end b = B.new b.save 5
  6. 委譲 class A def initialize(object) end def save object.save end

    end class B # object を汚染しない end class C end a = A.new(B.new) a.save a = A.new(C.new) a.save 6
  7. モジュール インスタンスを生成しない 例:helper グローバルでアクセスが可能。 moduleではなくclassにしていく。もしくはnamespaceとして使 う。 7

  8. concernについて ActiveSupport::Concern 使用用途:ApplicationRecordに共通のクラスメソッド、インスタン スメソッドを追加する クラスのトップレベルの共通化。 使用頻度を少なく 8

  9. クラス インスタンス化 メソッドのスコープを限定できる オブジェクト! models配下に振る舞いのクラスを生成していく ActiveModel、デザインパターン、委譲 transactionは明示的に行う 9

  10. FormObject (ActiveModel) フォーム表示するための振る舞いを分離したクラス validationも配置可能 Serviceクラスでも可 10

  11. モジュール module Seachable extend ActiveSupport::Concern def self.seach(params) end end class

    User include Seachable end # Usage User.search(params) 11
  12. Formオブジェクト class UserSearchForm include ActiveModel::Model def self.search(search_params) end end class

    User # object を汚染しない end # Usage UserSearchForm.search(params) 12
  13. Callback Railsのcallbackの影響 モデル同士の結合度の高さ 完結したユニットテストがかけない ActiveModel::Callbacksを使用 transactionは定義 Decoratorパターンで作成したクラスで処理を完結させる。 13

  14. ActiveRecordのcallback class User before_create :join_project def join_project self.project = Project.create()

    end end user = User.new user.save 14
  15. Decoratorパターンで役割を分離した例 class UserCreateDecorator include ActiveModel::Model attr_accessor :user define_model_callback :save before_save

    :set_project def save User.transaction do run_callbacks(:save) do @user.save end end end def set_project @user.project = Project.create end end user = UserCreateDecorator.new(User.new) user.save 15