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

torikago - Ruby::Boxで照らすモジュラモノリスの実行境界

Avatar for nori nori
July 19, 2026

torikago - Ruby::Boxで照らすモジュラモノリスの実行境界

Avatar for nori

nori

July 19, 2026

Other Decks in Programming

Transcript

  1. 用語 Rootモジュール モジュールとして隔離しない、app 直下のModel, Controllerなどの総称 Package API 他のモジュールからの呼び出しを 許可するクラス・メソッド 📁

    Project/ ├── 📁 app/ │ ├── 📁 controllers(root module)/ │ │ └── 📄 application_controller.rb │ └── 📁 models(root module)/ │ └── 📄 customer.rb ├── 📁 modules/ │ ├── 📁 bar/ │ │ └── 📁 app(bar module)/ │ │ ├── 📁 models/ │ │ │ └── 📄 product.rb │ │ └── 📁 package_api/ │ │ └── 📁 bar/ │ │ └── 📄 products_query.rb │ └── 📁 foo/ │ └── 📁 app(foo module)/ │ └── 📁 controllers/ │ └── 📁 foo/ │ └── 📄 dashboards_controller.rb └── 📁 queries/ └── 📄 customers_query.rb
  2. Rootモジュールは参照できる RootモジュールのQueryクラスを呼び出す例 class Foo::DashboardsController def index @customers = ::CustomersQuery.new(page: 1).call

    # => #<ActiveRecord::Relation [#<Customer ...>, ...]> end end RootモジュールのModelを継承する例 class Foo::Customer < ::Customer scope :filter_by_foo_logic, -> { … } end
  3. モジュール外からの参照ルールを定める Gatewayはモジュールの参照ルールによって呼び出しを許可する 許可されていない呼び出しが発生したら、例外を投げる class Foo::DashboardsController @products = Torikago::Gateway.build("Bar::ProductsQuery", page: 1)

    .invoke(:call) # => #<ActiveRecord::Relation [#<Bar::Product ...>, ...]> end class Baz::DashboardsController @products = Torikago::Gateway.build("Bar::ProductsQuery", page: 1) .invoke(:call) # => Torikago::DependencyError: module dependency not allowed end
  4. パフォーマンスの計測結果 観測対象 Ruby::Box無効 Ruby::Box有効 差 Rails boot 456ms 2,830ms 6.2倍

    Root API 初回リクエスト 16ms 449ms +433ms Root API 2回目以降リクエスト 2.6ms 4.3ms +2ms Root API 2回目以降 スループット 763.6 rps 688.2 rps 9.9%低下 モジュールのAPI初回リクエスト 14ms 445ms +431ms モジュールのAPI2回目以降リクエスト 2.2ms 4.3ms +2ms モジュールのAPI 2回目以降 スループット 770.3 rps 691.8 rps 10.2%低下