Slide 1

Slide 1 text

2022-10-21 Kaigi on Rails 2022 STORES 株式会社 CTO 藤村大介 既存Railsアプリ攻略法 CTOが見ること・やること・考えること

Slide 2

Slide 2 text

自己紹介 - お仕事 2 時期 2008~2012 2013~ 2015~ 2020~ 会社 いろいろ Quipper マチマチ STORES バックエンド Rails Rails Rails Rails, etc. フロントエンド jQuery, Backbone.js etc. Backbone.js etc. React.js React.js, Vue.js 立場 ほぼメンバー いわゆるEM CTO CTO 藤村大介 twitter.com/ffu_ github.com/fujimura note.com/fujimuradaisuke

Slide 3

Slide 3 text

自己紹介 - 書いたり発表したもの 3 Rails Developer Meetup 2019 入門 名前 WEB+DB PRESSの特集のダイジェスト版 https://speakerdeck.com/fujimura/ru-men-ming-qian WEB+DB PRESS Vol.110 特集 名前付け大全 「よい命名とは」をガチで考えてみたやつ https://gihyo.jp/magazine/wdpress/archive/2019/vol110

Slide 4

Slide 4 text

自己紹介 - ポッドキャスト 4 論より動くもの.fm 藤村がホストになって、技術や技術にまつわることについてざっくばらんに話す Podcastです。 文字起こしもあるよ! 論より動くもの.fm | Podcast on Spotify 論より動くもの.fm on Apple Podcasts 論より動くもの.fm カテゴリーの記事一覧 - STORES Product Blog

Slide 5

Slide 5 text

自己紹介 - 代表作 5 Haskellのプロジェクト生成ツール $ bundle gem みたいなやつ。当 時いいツールがなかったので作った git-grepの結果で置換とリネーム $ git grep | xargs sed -i s/foo/bar/ が面倒なので作った rspec-railsのHaskell版 正確にはRackにあたる層のためのも の。無かったので作った

Slide 6

Slide 6 text

6

Slide 7

Slide 7 text

STORES のミッション こだわりや情熱、たのしみに駆動される経済をつくる 熱中しているひとたちから生み出される、 多様な商品やサービスが街に溢れる世界。 その経済を支える、デジタルインフラを提供する。 7

Slide 8

Slide 8 text

サービス紹介 8 お店のデジタルを まるっとサポート。 個人や中小事業の方々に向けて、 お店のデジタル化をまるっと 実現できる価値を提供しています。

Slide 9

Slide 9 text

今日の話 9 ● 既存のRailsアプリケーションを触る機会は多い ● 目指すのは「プロダクト開発のアジリティを上げ、スムーズにお客さんに 価値を提供し続ける」こと ● ベテランRailsエンジニアおよびCTOとして、どういう観点で何を見て、何 を目指してどんなことをするのか? ● 裏テーマ:PMIで何をするか、CTOという経営幹部がRailsアプリケーショ ンを触るときに何を考えているか

Slide 10

Slide 10 text

最近のお仕事 10 ● PMI ○ = Post Merger Integration ○ M&Aのあとに経営とかプロダクトとか組織とかをいい感じにして1つ のチームになるやつ

Slide 11

Slide 11 text

2021年夏 SHOP FORCE社がSTORESにジョイン 11 ● 夏にSHOP FORCE社がSTORES(当時はhey)にジョイン ● 中目黒のSHOP FORCEオフィスに出社しはじめる ○ くわしくはこちら: 入社してすぐ任されたショップフォースのPMI。 STORES ブランドアプリ をリリースするまで|STORES People

Slide 12

Slide 12 text

2021年夏 SHOP FORCE社がSTORESにジョイン 12

Slide 13

Slide 13 text

中目黒に行くようになってすぐの状況理解とアクションプラン 13 ● パッと見た感じ、課題は色々ある ● ひとまず、優先順位はあまり気にせず、手当たり次第に直す! ● Low Hanging Fruitsがめっちゃある。これらを収穫しまくったあとで中長 期的な大きな優先順位は考えよう、と思った ○ 良く言えばOODA Loop、悪く言えばただのゲリラ戦

Slide 14

Slide 14 text

中目黒に行くようになってすぐの状況理解とアクションプラン 14 ● 「優先順位はあまり気にせず、手当たり次第に直す!」 ● とはいえ、手当り次第にも観察と方向決定があったはず ● 何を見て、何のために、何をしたの?

Slide 15

Slide 15 text

既存Railsアプリ攻略法 CTOが見ること・やること・考えること あるいはスタートアップPMI戦記 Rails編 ということではじまり! 2022-10-21 Kaigi on Rails 2022 STORES 株式会社 CTO 藤村大介

Slide 16

Slide 16 text

まずは概要をつかむ 16 とりあえず規模感とざっくりした雰囲気、全体像を把握しようとしました。

Slide 17

Slide 17 text

概要理解: $ rake routes 17 ● 目的 ○ どんなエンドポイントがあるのか、URLの雰囲気をざっくり掴む ● 見ること ○ $ rake routes をじっと眺める ○ テキストファイルに落とすと便利 ● わかること ○ 量と種別 ■ どのくらいの量のエンドポイントがあるのか? ■ HTMLを返すいわゆるRailsのView、API、よくわからないやつがそれぞれどのくらい あるか ○ 質 ■ APIのバージョニングは? ■ URL設計の品質はどうか? ■ リソース設計で色々見えてくる

Slide 18

Slide 18 text

概要理解: $ rake stats 18 ● 目的 ○ 何がどのくらいあるかざっくり掴む ● 見ること ○ $ rake statsをじっと眺める ● わかること ○ モデルはいくつあるか ■ 規模感を測るうえで一番わかりやすい指標。500を超えると気合いが入ってくる ○ テストはどのくらい書かれているか ■ Code to Test Ratioと、System/Request/Unitそれぞれ分量の割合をみる ○ JavaScriptはどのくらいあるか ■ フロントエンドの作り込み具合がわかる ○ Rails標準以外のディレクトリはなにがどのくらいあるか? ■ 設計思想がわかる ○ 非同期処理の割合は? ■ どのくらい非同期処理にするかは結構リポジトリによって違う

Slide 19

Slide 19 text

概要理解: Gemfile, package.json 19 ● 目的 ○ どんなライブラリが使われているのか把握する ○ 選球眼とノリを理解する ● 見ること・考えること ○ deviseは使われているか? ■ 認証周りの読み方に大きな差が出る ○ 設計に踏み込むタイプのGemは使われているか? ■ Railsのレールに乗って素朴に作るか、大きめのライブラリを使って組むかのノリがわ かる ■ pundit、cancancanあたり ○ 主要なライブラリのバージョンは? ■ アップデート大変そうなやつをみたり ○ ファイル保存系ライブラリは何を使っている? ■ Paperclipだとオッとなる ○ 知らないGemはあるか?あるなら、それは何なのか? ○ メンテナンスされていないことがわかっているGemはあるか?

Slide 20

Slide 20 text

概要理解: モデルの行数 20 ● 目的 ○ 重要なモデル、デカいモデルを把握する ● 見ること ○ $ git ls-files app/models | xargs wc -l | sort ○ 多くのことをやっているモデルはなにか ○ メチャクチャに大きいモデルはあるか ○ user.rb に匹敵するやつはどれ?

Slide 21

Slide 21 text

概要理解: モデルのテストの行数 21 ● 目的 ○ 重要なモデル、デカいモデルを把握する ○ 見ること ● $ git ls-files spec/models | xargs wc -l | sort ○ 重要もしくは複雑なモデルはどれか? ○ テストケースが多いモデルは重要度もしくは複雑性が高いと考えられる

Slide 22

Slide 22 text

概要理解: app/models/user.rb 22 ● 目的 ○ そのリポジトリでのコードのスタイルを把握する ○ 仕様や実装の観察と理解 ● 見ること ○ app/models/user.rb を流し読みする ● 考えること ○ 様々な観点があるが、いったん事前の観点を捨てて流し読みすると、様々なことがわかる ○ user.rb はお手入れが行き届いている場合が多いので、そのリポジトリでのRubyコード の書き方の癖みたいなものもわかる

Slide 23

Slide 23 text

概要理解: config/initializers/* 23 ● 目的 ○ 実装の観察と理解 ● 見ること ○ ここには色々なものが眠っているので、これも同じく事前の観点を捨てて一通り流し読み して状況把握する ■ ミドルウェア、外部のAPI、などなど ○ 各種クレデンシャルの扱い方の癖を通して、なんとなくDevOps的な練度がわかる

Slide 24

Slide 24 text

概要理解: コードの質感 24 ● 目的 ○ スタイルの理解 ○ 可読性、修正容易性、セキュリティのために直すべきところの発見 ● 見ること ○ コードフォーマット ○ idiomaticなRubyコードか ○ eval, send, method_missing など大胆な技術の使われぶり

Slide 25

Slide 25 text

概要理解: 開発環境 25 ● 目的 ○ オンボーディングコスト削減のためにするべきことの発見 ● 見ること ○ どのくらいdocker-composeに乗っているか ○ seeds.rb で開発に使えるデータが作られるか ○ ドキュメントの通りに作れるか ● 考えること ○ ここは考えずに片っ端から直す

Slide 26

Slide 26 text

概要理解: テスト・CI 26 ● 目的 ○ 品質保証やデリバリーの練度の把握と、改善方針を考えるための材料集め ● 見ること ○ そもそもあるか(テストもCIも) ○ 実行時間はほどほどになっているか ○ どのくらい安定しているか ■ Flakyなテストはどこにあるか ○ CIの通過をもってどのくらいアプリケーションが正しく動作するか確認できるか ■ これはもともといたメンバーに感触を聞くのが早くて正確

Slide 27

Slide 27 text

概要理解: リリース手順・サイクル 27 ● 目的 ○ 可能な限り自動化し高頻度でリリースするために何をするべきか把握する ● 見ること ○ リリース手順は自動化されているか ○ リリースサイクルは明文化されているか ○ されている場合、手順が明確か ○ 頻度はどうか

Slide 28

Slide 28 text

概要理解: 監視 28 ● 目的 ○ 運用で改善する点はあるか確認 ○ パフォーマンスはいかほどか ● 見ること ○ APM ■ Datadog、New Relicなど ○ AWSの各種ログ

Slide 29

Slide 29 text

概要理解 まとめ 29 ● $ rake routes ● $ rake stats ● Gemfile ● package.json ● モデルの行数 ● モデルのテストの行数 ● app/models/user.rb ● config/initializers/* ● コードの質感 ● 開発環境 ● テスト・CI ● リリース手順・サイクル ● 監視 といったあたりの把握で、だいたいどんなRailsアプリケーションがどのように動いているのかわかり ました。 では直しますか…とその前に!

Slide 30

Slide 30 text

既存Railsアプリに触れるときの心構え 30 あるいは、新たに事業/プロダクト/コードを受け入れるときの心構え

Slide 31

Slide 31 text

心構え: 事業をやっていると、常にあらゆる状況でベストなコードは書けない 31 ● その時はベストなコードでも、状況が変わるとベストではなくなることがある ○ そして、状況は変わっていく ● そもそも時間の都合でベストのコードが書けない場合もある ○ スタートアップという、来月生きるか死ぬかの世界では特にそう ● なので、ベストではないコードはどうしても生まれる ○ 何も悪くないし避けられない

Slide 32

Slide 32 text

心構え: 「良くない」と思うコードに腹を立てても意味はない 32 ● 実業界で出会うコードは、それぞれにそれぞれの事情があって、現状がある ● 生き延びた事業のプロダクションコードは形はどうであれ尊い ● なんにせよ、やれることは直すか、直さないかしかない ○ 我々プログラマーは直すことができる。直そう

Slide 33

Slide 33 text

心構え: 毎日少しづつ改善すれば必ずよくなる 33 ● 事業存続に影響があるくらい内部品質が悪ければ、作り直す判断もあるだろう ● しかし、だいたいのプロダクションコードは漸進的に改善できる、と僕は思っている ○ 今回もそうだった ● 「直る」という事実で、改善を積み上げて課題を解決する文化を作りたかった

Slide 34

Slide 34 text

心構え: いったん「しゃがむ」判断も大事 34 ● 「プロダクト開発のアジリティを上げ、スムーズにお客さんに価値を提供し続ける」ために内部 品質の改善は重要 ● しゃがむ=内部品質の改善に時間を使う必要があれば、その判断をし、関係者の理解をとりつ け、実行する ○ この意思決定と実行を行うのは、ソフトウェアエンジニアの仕事 ○ これをやるには、関係者との強固な相互理解・信頼関係が必要 @t_wada さんの 質とスピード(2022春版、質疑応答用資料付き) 53p より

Slide 35

Slide 35 text

既存Railsアプリに触れるときの心構え まとめ 35 あるいは、新たに事業/プロダクト/コードを受け入れるときの心構え まとめ ● 新しい事業/プロダクト/コードに触れるときは、 ○ とにかく毎日少しづつ改善する ○ その上で「しゃがむ」必要があれば決断し、しゃがむ ■ 「プロダクト開発のアジリティを上げ、スムーズにお客さんに価値を提供し続ける」 ために内部品質を改善する ○ そのために関係者との強固な相互理解と信頼関係を作る

Slide 36

Slide 36 text

やったこと 36 ということで、概要の把握と心構えができたので、実際に何をしたかを紹介します。

Slide 37

Slide 37 text

やった: 開発環境の整備 37 ● 目的 ○ 新メンバーのオンボーディングコストを減らす ● やったこと ○ rails db:seeds が通るようにする ○ docker-compose化が部分的だったので、完遂 ○ 不要な環境変数を削除するなど ○ 環境構築のドキュメントをesaからリポジトリのREADMEに移す ○ レビューによる知識の共有や更新性のため、リポジトリに置いておいたほうが良い

Slide 38

Slide 38 text

やった: デプロイプロセスの自動化 38 ● 目的 ○ プロダクト改善速度の向上、障害対応コストの削減 ● やったこと ○ もともとmasterにマージされると本番にデプロイされるようになっていたが、頻度は随 時、リリース用のPRは手動作成だった ■ 結果、リリースの単位は比較的大きくなっていた ○ リリース用のPRの作成をGitHub Actionsで自動化し、週二回の定期リリースとした ■ 頻繁なリリースによりチームの「リズム感」も良くなった

Slide 39

Slide 39 text

やった: 内部品質改善に時間を使うという意思決定 39 ● 目的 ○ スムーズにお客さんに価値を提供し続けるため、プロダクト開発のアジリティを上げる ■ 内部品質に改善の余地があり、ここの改善が数ヶ月後のプロダクト改善速度に大きく インパクトがあると判断した ■ 定量にするまでもなく、感覚的に明らかだった ● やったこと ○ 他業種のチームメイトとの相互理解、信頼関係を作る ■ 事業担当、PdM、サポート、経営メンバーなど ■ ランチ、1on1、飲み会、ふとした雑談などで、人として打ち解ける ■ おれたちRubyistは“Nice” であるということを知っているはず…! ○ 内部品質改善の価値を理解してもらう ■ @t_wada さんの「質とスピード」を読んでもらったり、自分で読み直して説明した りするとよい ○ 時間を使うと決め、合意をとりつけ、改善に取り組む ■ なぜ?がソリッドなら、ビジネス側のひとも理解してくれます

Slide 40

Slide 40 text

やった: feature specからsystem specへの移行 40 ● 目的 ○ 新しく標準的な手法に変更してメンテナンスコストを削減 ● やったこと ○ まずはfeature/system spec以外への副作用をなくす ■ RSpec.configure do 内を整理してFeature spec用のものを spec/feature_helper.rb に切り出し ○ Feature Spec用とそれ以外でも使うやつが混在していたヘルパーメソッドを分類 ○ system specへ移行 ■ spec/system_helper.rb を新設 ○ 少しづつ書き換えて問題なさそうだったのであとは一括置換などでガッと

Slide 41

Slide 41 text

やった: 使われていないコード、Gemの削除 41 ● 目的 ○ 実装時の認知負荷軽減による生産性改善 ○ あらゆる作業に細かく大量に積み上がっている見えないコストだと思っている ○ 部屋が散らかっていると集中できないのと同じ ● やったこと ○ 明らかなものから、毎日着実に消していく ○ 細かく着実に消していけば必ずキレイになります ■ 部屋の掃除と同じ ○ 副業のチームメンバーにお願いしたりもした ■ 頼みやすいし、手をつけやすいタスク

Slide 42

Slide 42 text

やった: RSpecのfilter runを有効にする 42 ● 目的 ○ 僕が欲しかったので。。。 ● やったこと ○ + config.filter_run_when_matching :focus

Slide 43

Slide 43 text

やった: s/FactoryBot.create/create/ 43 ● 目的 ○ 認知コスト削減 ○ Spec内に大量に出てくる FactoryBotという文字を脳が認識しているが、そのコストがもっ たいない ● やったこと ○ 一括置換 ○ $ git gsub 'FactoryBot.(create|build)' '$1' spec ■ https://github.com/fujimura/git-gsub 便利ですよ(宣伝)

Slide 44

Slide 44 text

やった: transactional testを有効にする 44 ● 目的 ○ 遅い!!! ● やったこと ○ Database CleanerのStrategyが truncation でテストの実行が遅かったのでtransaction にして速くした ■ strategy = :transaction で実行して通ったら実行時にExampleのMetadataを 書き換えるようにした ■ くわしくはこちら RSpecのテストコードを実行時に書き換えて実行速度を改善した話 - STORES Product Blog

Slide 45

Slide 45 text

やった: Request specで叩くエンドポイントはリテラルを使う 45 ● 目的 ○ Request Specがエンドポイントの検証になっている状態にしたい ○ テストで post_path などnamed routesが使われていた ○ エンドポイントの検証という意味では、文字列リテラルのほうがよいと判断 ■ get post_path ではなく get “/post/#{post.id}” としたい ● やったこと ○ テスト実行時にnamed routesを文字列リテラルに書き換える仕組みを作り改善した ■ transactional testを直したときの仕組みを流用

Slide 46

Slide 46 text

やった: annotate自動化 46 ● 目的 ○ 人間の仕事を減らしたい ● やったこと ○ たまに人間がやる、ずれることもある、という感じだった ○ GitHub Actionsでmasterにコミットがあったらannotateを実行して、差分があれば自動 でBotがPRを出すようにした https://github.com/ctran/annotate_models

Slide 47

Slide 47 text

やった: 開発環境SSL化 47 ● 目的 ○ サードパーティーのインテグレーションがある機能をローカルで使えるようにする ○ ID連携など。できていないとSSLが必要な処理がローカルでテストされることはないし、必 要になってから整備するのは遅い。なので先にやっておく ● やったこと ○ オレオレ証明書を発行してMac OSのKeychainにインストールするスクリプトを書き、 docker-composeでnginxのリバースプロキシを立てて…というよくあるやつ ○ OpenSSLで作ったけどmkcertでもよかった

Slide 48

Slide 48 text

やった: rubocop --auto-correct 自動実行 48 ● 目的 ○ コードフォーマットやスタイルを揃えて、読むときの認知コストを下げたい ○ 認知コストはまじで我々の可処分時間と注意力を奪っていると思うので、下げるの大事だ と思っている ● やったこと ○ See たまってしまった .rubocop_todo.yml をGitHub Actionsで継続的かつ自動的に倒す方 法 - STORES Product Blog ■ 要は rubocop –auto-correct をGitHub Actionsで実行、 .rubocop_todo.yml を再生成、 PRを出す、するやつ ○ prettier-rubyにすればよかったかも、という後悔はある

Slide 49

Slide 49 text

やった: rubocop --auto-correct 自動実行 49 .rubocop_todo.yml の行数の推移(グラフを出すコードはこちら)

Slide 50

Slide 50 text

やった: Trailing Whitespaces一斉削除 50 ● 目的 ○ 認知コスト削減 ● やったこと ○ $ git ls-files app spec lib config | grep -E '.rb$' | xargs gsed -r -i 's/\s+$//

Slide 51

Slide 51 text

いろいろやった!! 51 だいぶ、よくなりました

Slide 52

Slide 52 text

再掲:既存Railsアプリに触れるときの心構え 52 あるいは、新たに事業/プロダクト/コードを受け入れるときの心構え まとめ ● 新しい事業/プロダクト/コードに触れるときは、 ○ とにかく毎日少しづつ改善する ○ その上で「しゃがむ」必要があれば決断し、しゃがむ ■ 「プロダクト開発のアジリティを上げ、スムーズにお客さんに価値を提供し続ける」 ために内部品質を改善する ○ そのために関係者との強固な相互理解と信頼関係を作る

Slide 53

Slide 53 text

やったこと まとめ 53 ● 開発環境の整備 ● デプロイプロセスの自動化 ● 内部品質改善に時間を使うという意思決定 ● system spec移行 ● 使われていないコード、Gemの削除 ● RSpecのfilter runを有効にする ● s/FactoryBot.create/create/ ● transactional testを有効にする ● Request specで叩くエンドポイントは実際の値を使うようにしていく ● annotate自動化 ● 開発環境SSL化 ● rubocop --auto-correctを定期実行してPRを出す ● Trailing whitespaces一斉削除

Slide 54

Slide 54 text

再掲:既存Railsアプリに触れるときの心構え 54 あるいは、新たに事業/プロダクト/コードを受け入れるときの心構え まとめ ● 新しい事業/プロダクト/コードに触れるときは、 ○ とにかく毎日少しづつ改善する ○ その上で「しゃがむ」必要があれば決断し、しゃがむ ■ 「プロダクト開発のアジリティを上げ、スムーズにお客さんに価値を提供し続ける」 ために内部品質を改善する ○ そのために関係者との強固な相互理解と信頼関係を作る

Slide 55

Slide 55 text

やったこと まとめ 55 ● 開発環境の整備 ● デプロイプロセスの自動化 ● 内部品質改善に時間を使うという意思決定 ● system spec移行 ● 使われていないコード、Gemの削除 ● RSpecのfilter runを有効にする ● s/FactoryBot.create/create/ ● transactional testを有効にする ● Request specで叩くエンドポイントは実際の値を使うようにしていく ● annotate自動化 ● 開発環境SSL化 ● rubocop --auto-correct を定期実行してPRを出す ● Trailing whitespaces一斉削除

Slide 56

Slide 56 text

既存Railsアプリ攻略法 CTOが見ること・やること・考えること まとめ 56 ● 見ること・やること ○ 資料を見てくれ ● 考えること あるいは心構え ○ 新しい事業/プロダクト/コードに触れるときは、 ■ とにかく毎日少しづつ改善する ■ その上で「しゃがむ」必要があれば決断し、しゃがむ ■ 「プロダクト開発のアジリティを上げ、スムーズにお客さんに価値を提供し続 ける」ために内部品質を改善する ■ そのために関係者との強固な相互理解と信頼関係を作る

Slide 57

Slide 57 text

ご清聴ありがとうございました 57 今日の話の内容が何かしら皆さんのお役に立てると幸いです。 この話、もしくこの話と関係ない話などなど よかったらぜひお話しましょう〜 Meetyでお気軽にご連絡ください!