Kaigi on Rails2023参加レポート
はじめに
株式会社マイベストでバックエンドエンジニアをしています、片田恭平(@katakyo_51)です!
Kaigii on Rails 2023(2023年10月27日〜28日開催)に参加したので参加レポートを残そうと思います。
弊社マイベストもRubyスポンサーをしており、今回は初のオフラインの開催と合わせて、ブースも出させていただきました。
Day1
印象に残ったセッション、スライド、感想をまとめます。当日見れなかったものはアーカイブの動画を見て見返したりしています。
基調講演 準備中
zakk氏のこれまでのキャリアの話やRailsと歩んできたこと共有しながら、OSSに貢献するメリットやRailsをより理解する方法に関しての話をしていただき、最後に直近で取り組んでいるRails CIを事例にOSSへの貢献方法を説明していただきました。
OSSの貢献方法として、ドキュメントの更新や修正ははじめの第一歩として良いこと
zakk氏はRailsガイドの更新をしていいたそうです。単に情報を追加するだけでなく、読み手に対してわかりやすくするように段落を分割したり、読みやすくすることも貢献の一つだということ。
自分で貢献できるバグを特定することにも役立つということ
ドキュメント更新を手間を減らすためにCI/CDを整えたり、markdownのフォーマットを整えるためにLinterツールrubocop-md やmarkdownlintを使ったこと
Railsをより理解するための方法
RailsConfのトークをYoutubeで視聴してみるのが良い(zakk氏が良いトークリストをYoutubeでまとめて公開してくださっています)
RailsのissueやPRは読むべき(時間がなければThis Week in Railsを読むといい)プルリクではバグレポートの書き方やバグの特定の仕方なども勉強になるとのこと
Rails CIへの取り組み
Railsのリポジトリ自体にはCIのソースコードはなく、別リポジトリで管理している(buildkite-config)→様々なバージョンのサポートを担保するために全ての安定したブランチに変更をバックサポートするため
貢献のモチベーションとしてCIの経験が豊富なこととCIを使いたいプロジェクトがたくさんあること
全ての内容を完全に理解することはできていませんが、自分自身まだOSSへのContributeはできていないのでとても参考になる話でした!issueはバグに遭遇した時にたまに検索で引っかかって見に行きますが、日常的に言語やフレームワークのPRやissueを眺めることは大変力になると感じとても良い刺激をいただきました!
Rails アプリの 5,000 件の N+1 問題と戦っている話
最近、会社の技術課題で初めてパフォーマンスチューニングに取り掛かったので、興味深いセッションでした。初学者向けにN+1問題とは何か、Bulletを使えばログに出力できる話、件数が多いと手動でincludesメソッドを入れるのはツライので、BulletmarkRepairというgemを作った話。includesとpreloadとeager_loadの話と実際の業務でのN+1問題の解消のための取り組みに関して説明されていました。
面倒なところはgemにして自動でやるようにしたり、incluedsとpreloadとeager_loadの挙動の違いが自分はあまりよくわかっていなかったのでとても参考になりました!
生きた Rails アプリケーションへの delegated types の導入
Delegated Typeの話でした。業務でDesignDocsを書く機会も増え、ポリモーフィック関連やSTIの話は聞いたことがありましたが、Delegated Typesは初めて聞きました…..
STIだとテーブルが一つになりSQLクエリがシンプルになるといったメリットがある一方で、カラムが増えたり、レコード内にNULLが増える、サブクラスの固有のカラムにNOT NULL制約をかけられないといったデメリットが出てしまいます。
Delegated Typeとは、STIの代替として使える仕組みとして出た機能で、似たような機能を持つテーブルに対して、共通部分と固有に必要になった情報は別テーブルに切り出し、アソシエーションで紐付ける方法だそうです。(ポリモーフィック関連に近い機能な気がします)
共通テーブルに外部キー制約をかけられないといったデメリットがありますが、共通で何かカラムを追加したい場合は共通テーブルにカラムを増やすだけで実装が終わりますし、固有な情報だけ改修したい場合はアソシエーションで紐づけられたテーブルにカラムを追加しやすくなるので、テーブル設計の選択肢として今後は頭に入れておきたい機能だなと思いました!
やさしいActiveRecordのDB接続のしくみ
ActiveRecordとDBの間でどのような通信のやり取りが行われているかが丁寧に解説されたセッションでした。
はじめに、クライアント・サーバー間の接続と接続確認はどのように行われているか、それからより解像度を上げてActiveRecordのアダプター(mysql2)とMySQLの通信しくみを解説してざっくり全体像を掴んだ上で、さらに詳細に入ります。
ActiveRecord内の主要なクラスとして以下の3つのクラスが解説されていました。
Mysql2Adapters
実際にmysql2アダプターを呼び出すクラス
mysql2のクライアントインスタンスであるMysql2::Clientを作成する
DBに対して接続要求を行えるようになる
ConnectionPool
接続を管理するクラス
接続プールから接続の新規作成かプールから再利用するかを管理する
ConnectionHandler
複数ある接続プールからどの接続プールを使うか管理するクラス
さらに細かくConnectionHandlerからownerごとにPoolManagerを作成し、roleとshardごとにPoolConfigを作成してConnectionPoolを作成し、mysql2アダプターを介してDBへの情報の接続が行われていることが説明されていました。
情報の前提から解説し、より詳細を話あと実際のコードとイメージ図を使った解説があったので、わかりやすかったです!普段何気なく使っているActiveRecordの解像度が上がった気がしますし、どのレベルでエラーが起きているのかあたりをつける意味でもより理解したいなと感じました!
初めてのパフォーマンス改善 ~君たちはどう計測するか~
ボトルネックになっている原因をどう考えて調査するのか、調査結果や修正をどうまとめるのかに関して説明されていました。
調査
APMを見て全体像を把握する→どのページ/アクションが遅いのか把握する
個別にAPMで確認する
遅い部分が原因っぽいものを確認する→詳細把握はせずにどこのレイヤーで遅いのか把握して時間をかけずに当たりをつける
対応の優先順位を決めたり、調査結果をまとめる(原因やボトルネックが単一なのか複数なのかなど)
検討、計測
はじめにテストを書いておく(改善後振る舞いが変わらないことを担保するため)
推測と計測をしてどんどん試していく
ちょうど先日社内で初めてパフォーマンス改善に取り組んだのですが、原因特定に時間がかかったり、調査方法をどうまとめれば良いのかわかっていなかったので参考になりました。「コードにしたものとコードにしなかったことがプログラミング」という言葉の中にもあるように、修正前のソースコードと修正後の差分で何が起きたのか説明するのがPRであるのでレビュワーが理解しやすいように丁寧にPRを書こうとモチベーションが上がるセッションでした!
Turbolinksアレルギー患者に捧げるTurbo & Stimulusでの時短実装術
Rails7からRailsのデフォルトになった、モダンなWebアプリケーションを作るための新しいアプローチであるHotwireのTurboとStimulusの説明がされていました。先日パーフェクトRailsの輪読会で4章の部分でちょうど触れたので、内容はかなり頭に入りやすかったです。
実例として、ログイン画面時の確認フォームをモーダルで表示するようにして少ないコード量で実装したり、ラジオボタンを動的に変えるといったことも少ないコード量でできるとのことです。個人開発や何かのサービスのプロトタイプを高速で実装するのに使えそうな技術だなと思いました!(懸念点としては古いブラウザで動かないらしいです)
Day2
事業の試行錯誤を支えるコードを捨てやすくしてシステムをシンプルに保つ設計と工夫
損失回避バイアスのため、実際には使われていない機能も工数をかけて作ったものを捨てるという意思決定は難しいが、事業初期は試行回数を増やすためやコードの複雑性やメンテナビリティを考えて使われなくなった技術は捨てる意思決定も大事という話がされていました。
テーブルごとに情報を分離すること、view層になるべく分岐を入れないような設計をすれば撤退コストがかからない形で設計ができる。
実装前のminispec(仕様案のようなもので)KPIなどの指標でうまくいかなかったときのアクションを事前に決めておくことが大事とのこと。
業務で新規機能の設計や実装を行うことがありますが、将来的にユーザーに使われていないものを撤退するということも見越して仕様や設計の検討をしていきたいと感じました!
Fat Modelを解消するためのCQRSアーキテクチャ
YOUTRUST社が実際に扱っているアーキテクチャに関しての話がされていました。
Fat controllerやFat modelに対応するために、CQRSアーキテクチャを採用し、さらにcommandの前に独自にUseCaseを追加している。UseCaseは複数のCommandを組み合わせて呼び出す役割をしている
これらのアーキテクチャのメリットとして大きく3つがあるとのことです
ModelやControllerの肥大化を防ぐことができる
参照系と更新系のデータソースを分けることが簡単になる
ファイルごとに更新や参照の責務を分離することで、単体テストが書きやすくなる(責務がはっきりすることで重複したテストが生み出されることを防ぐことができたり、一部はモックデータを使うため処理が軽い使いまわせるというメリットもあるそうです!)
YOUTRUST社はサービスのサンプルコードも公開しているので、実際の使われ方を見たい場合はこちらのリポジトリを見てみるのが良さそうです!https://github.com/team-youtrust/sample-webapp
32個のPRでリリースした依存度の高いコアなモデルの安全な弄り方
MySQLのオンラインDDLという機能に関しての解説とアプリケーション開発において、サービスを停止させないように安全にテーブル定義を変更するための手順に関しての話がされていました。
オンラインDDLはMySQL5.6で追加された機能でサービスを停止することなくカラム追加をすることができる機能でMySQL公式の説明にもカラム名の変更や追加はオンラインDDL対象なので素直にやってしまうと引っかかってしまう罠に関して説明がありました。
オンラインDDLが非対称になるケース
オンラインDDL対象外のものが1つでも混ざるとDDLステートメントは全て非対称になる
MySQL5.5以前に作ったテーブルに対してのDDLは非対称
Generated Columnが存在するテーブルに対して、カラム位置を指定して追加するケース (カミナシ社のテックブログに具体的な事例が書かれていました)
メタデータロック
初期化のフェーズで共有メタデータロックを取得、テーブル定義のコミットのフェーズで排他的メタデータロックを取得する際に待ち時間が発生し、Waiting for table metadata lock エラーが生じる可能性がある
長期期間のロックを取得している処理がある場合は処理の実行タイミングとずらしたり、ロックの取得時間を短くする工夫が必要
オンラインDDLといってもカラム変更するのは、migrationとデプロイの時差によって状態の不一致期間が生じて安易にやるのは危険でカラムの追加→役割の置き換え→古いカラムの削除といった手順を踏むのが無難であるとのことでした。
実際に業務で何度かテーブルのカラム名を変更したことがあり、同じような手順を踏んでいますが、なぜこのような手順を踏むのかの理解度が上がりました!
管理機能アーキテクチャパターンの考察と実践
管理機能の特性と後追いで作られがちという性質を持つため、前提や制約つきでアーキテクチャを考える必要があるためそのアーキテクチャパターンに関しての解説がされていました。
紹介されていたアーキテクチャパターンとして
管理機能を密結合をさせる
Railsの強みを活かし最小のコストで開発できる(学習容易性やgem等のライブラリの豊富さなどの利点が使える)
密結合によるあらゆる問題が生じたり、過度にgemに頼ると変更容易性が下がることがデメリットとしてあげられていました
既存のBackendコードベースに管理機能を密結合させるとモノリシックコードベースに追加する恩恵を受けられるが、PDS順守で得たメリットを失うというデメリットもある
管理機能においてPDSを順守する
エンドユーザー向けと管理機能でFrontendと分離したいケースにおいてプレゼンテーション層の密結合を防げる
BackendにWeb APIの追加が必要なのと管理機能にFrontendの技術スタック取得やCI/CDの整備が必要といった
Microservices化により管理機能サービスを追加
Frontend、Backendともに疎結合になり、管理機能に完全に境界があるなら恩恵を受けられそう
一般的なマイクロサービスのデメリットやコストが生じる
アーキテクチャの選択に正解はないため、以下を考慮して選択する必要がある
どんなことを実現したいのか
実現する機能の特性
選択肢ごとのトレードオフ(メリデメ)
対象のドメイン
業務で管理画面/管理機能のFrontendやBackendのWebAPIを実装するケースがあるのですが、管理画面/管理機能のアーキテクチャに関して深く考察したことがなかったためとても面白かったです!
(余談ですが)当日サテライト会場で見ていて、登壇のはじめに何かが起こったようだったのですが、こんなことが起きていたとは笑
その他
セッション以外の現地ならではの良かった点に関してまとめます!
スポンサーブース
セッションの合間に全スポンサーのブースで話を聞きました(ノベルティーもいただきました)
個人的にはSmartBank社のB/43のアーキテクチャー図がすごく印象に残っていてエンジニアの方に質問しながら話を聞きました(帰ってサービスを入れたりカードを発行してみたので届くのが楽しみです)
弊社のスポンサーブースにもたくさんの方々が来てくださり、mybestのアプリをインストールしてくださる方もいたので嬉しかったです!
Startup Drinkup at Kaigi on Rails 2023
ROUTE06社とYOUTRUST社とDay1の後にDrinkupイベントを開催しました。
会場がKaigi on Railsの参加者で埋め尽くされるほど、たくさんの人に来ていただきました!
会場がダーツバーだったので自分は参加者の方とダーツして盛り上がっていました
ランチ
smartbank社の孤独のCTOグルメを参考にDay1は肉食堂・優さん、Day2は東京 MEAT 酒場 浅草橋総本店さんでランチをいただきました(どちらのお店もとても美味しかったです!)
アフターパーティー
会場を場面転換して、アフターパーティーで初めて会った方、すでにお知り合いの方と交流しました。Railsのことから事業の話などさまざまな話ができました!
(NFCカードを持っていったらX(Twitter)の交換がしやすかったのでおすすめです!)
感想
昨年もオンラインで視聴していましたが、昨年に比べてセッションの理解度が上がった気がします!(実際に業務でできることが増えた)
また、他社のブースに行ってサービスの話をしたりと懇親会等で交流しながら開発の話ができ、視野が広くなった気がします!
若手の方も積極的にスピーカーとして参加しており、オーディエンスとしてだけでなく来年はぜひプロポーザルを出してスピーカーとして参加したいとも思ったので、発表できるネタを日々貯めていきたいと思います!
最後にKaigi on Rails2023の運営の皆様には素敵なカンファレンスを企画、運営してくださり本当にありがとうございました!
宣伝
11/9にsmartbank社、メドピア社と合同でメドピア社のオフィスでアフターイベントやります!
参加枠が増えたので、興味があればぜひお越しください!(自分も行きます!)