※この記事は、2022 Speee Advent Calendar11日目の記事です。
昨日の記事はこちら
tech.speee.jp
こんにちは、DX事業本部エンジニアのさとーる(@satotoru2000)です。
私は今年の6月から「イエウール」というプロダクトのSEOコンテンツ開発チームで開発をしています。今回はその中でやったことをまとめながら、
モノリシックRailsアプリの一部のドメイン領域を担当する状況下で、自信をもって変更できる領域をどうやって広げたか?
という話をしようと思います。
当初のイエウールの課題
イエウールは、アーキテクチャ的にはいわゆる一般的なモノリシックRailsアプリです。下の図のように、一つのRailsアプリケーションにほぼ全ての必要な機能が乗っているような状態です。
また、サービスとしてもそれなりに歴史があるプロダクトで、立ち上げから8年以上が経過しています。そのため、以下のような問題がありました。
app/models/
直下にモデルが並べられており、何がどこに使われているのか分からない- 当時の担当者がいないので、どういった設計方針だったのかが分からない
- 全体を把握している人が誰もいない
こういった状況下で、SEO開発チームが関わる領域におけるコントロール可能領域を広げ、高いコードの品質と高いスピードを実現する必要がありました。
また、制約条件として以下がありました。
- メインメンバーは新卒1年目エンジニア数名。素晴らしいメンバーだが、混沌としたコードをよしなに修正する力はまだない
- ユーザへの価値提供を止めない。新規開発と並行して進めること。(つまり、大型のリファクタリングはしない)
この条件の中で、課題を解決するための方策を考え、実行していきました。
やったこと
自分達でコントロールできる聖域を作る
まずは、小さくていいので「ここは間違いなく自分達でコントロールできている」と自信をもって言える領域を作るところから始めました。既存のモデルの変更は何がどこに影響するかを完全に見通すことが難しいため、「正しく変更できているのだろうか?」という不安がつきまといます。
特にまだ入社したばかりの新卒エンジニアの場合、いきなりこれを見通しながら開発するのはあまりにもハイコンテキストで、心理的にも負担が大きいです。
そのため、名前空間やディレクトリを切り出して、なるべく依存関係の少ない「コントロール可能領域」を作り、そこを育てていく形で徐々に扱える領域を広げる戦略を取りました。
具体的にはこんなことしました。
Model側
- SEO開発用の名前空間を設定し、新しいモデルはそこに入れること
- (神モデル気味の)ActiveRecordを直接変更するのは極力避ける。代わりに名前空間配下にPOROやActiveModelを積極的に作り、そちらに処理を逃がす
View/Controller側
- SEO開発用のディレクトリを作り、新しいcontrollerやviewはそこに入れること
設計やコーディングに対する方針を明確にし、既存コードを取捨選択する
イエウールは「良いコード・悪いコード」に関する基準や、設計に関する方針を持てていない状態でした。いくつかの設計パターンは採用されているのですが、「今後も採用すべきなのか?非推奨なのか?」の指針がない状態でした。
そのため私たちのチームでも最初は「何かを変更するたびにそこで採用されている設計パターンを確認し、レビューでその良し悪しを判断する」状態になり、なかなかスループットが上がりませんでした。
特に新卒メンバーにとっては、暗黙知化した複雑なコンテキストを読み解きながら良し悪しを判断するのは困難なものでした。そのため、歴史をある程度把握している私が基準を提示してしまい、まずはその基準に従ってもらい、自律的にできるようになってから徐々にオーナーシップを持ってもらうことにしました。
そのため、以下をやりました。
- コーディング規約を策定。良し悪しの判断基準を明文化する
- お手本となるような実装をまず自分が作って見せる。それを真似してもらう
- 判断に迷う要素が出るたびに「今後も採用する設計」「もう踏襲しない設計」を決めて、コーディング規約にも反映させる
コーディング規約をチラ見せすると、こういったものを作りました。目的は「判断基準を作ること」ですので、ルールを書くというよりスタンスを書くことを意識しました。
当たり前水準を下回っているところは一気に引き上げる
上記を経て、バックエンドのコードはかなり見通しが良くなったのですが、フロントエンドに関してはもう少し根深い問題がありました。
具体的にいうと以下のような状態です。
- シンプルにSprocketsでバンドルされているので、import/exportが使えない。モジュールを簡単に分割する機構がない
- 構造や設計がない。必要に応じてjQueryスクリプトを新たに作っている
- 全体の読み解きが難しく、何がどこで読み込まれて動いているのかが分からない状態
- Lintが導入されておらず、コーディングスタイルがバラバラ
戦略としてはバックエンドと変わらないのですが、戦略を適用するまでに整えなければならない要素が多いなぁと感じていました。
そのため、いきなり設計方針を作らず、基盤を整えることから始めました。
まずは基盤整備として、以下を実施しました。
- js-bundling-rails + webpackを導入し、モダンなビルド環境の下でJavaScriptを書けるようにする
- プレーンなjQueryに代わるフレームワークとして、Stimulusを導入する
ここまで整うと前述の聖域を設定できるようになるので、順番に以下を実施しました
- webpackでコンパイルされる
app/javascript
配下を聖域と定め、Stimulus Controllerを経由したコードのみを配置することとする - ペアプログラミングで既存コードを1つStimulusに移行し、真似できるようにする
- Ruby側と同様にJavaScriptコーディング規約を定め判断基準を明確化する
まとめ
これらの戦略の実行を半年続けた結果、新卒メンバーがある程度自律的に開発できる環境を整えることができました。
以下にいくつか気づいたことを書いていきます。
チームが扱えるスコープと、システムのスコープを一致させるのが大事
最初にお話しした「自分達でコントロールできる聖域を作る」という戦略を、チーム視点で言い換えると「小さいところから成功体験を作りながら、少しずつ出来ることを増やしていく」という至極当たり前の結論になります。
この当たり前の結論をきっちりと技術戦略に埋め込むことができたのが今回の成功要因だったと思います。
個人的な信条として、技術的な意思決定をするときには「手触り感」をとても大事にしています。今回、混沌としたコードベースを前に大振りな意思決定に逃げることなく、チームの実力に合わせた手触り感のある意思決定を重ねたことが良かったのだと思います。
リードエンジニアとマネージャーは同時にやるから面白い
今回の取り組みを振り返ると、「チームの実力や将来性を材料に技術的な意思決定をする」という経験が自分の中でもとてもユニークだったと感じています。技術の意志決定は、もう少しピュアな事業課題というか、純粋なビジネス構造を抽象化していくものだと思っていた節もあったのですが、そうではないんだなということに気づきました。
私は肩書き的にはマネージャーでもあるのですが、チームでリードエンジニアとしてもコードを書いています。「メンバーの成長や期待をコードに込める」ような動きは、両方やってるからこそ出来たと思うし、両方やってるからこそ出せるバリューがあるなぁと改めて思いました。
さいごに
Speeeでは一緒にサービス開発を推進してくれる仲間を大募集しています!
こちらのFormよりカジュアル面談も気軽にお申し込みいただけます!
Speeeでは様々なポジションで募集中なので「どんなポジションがあるの?」と気になってくれてた方は、こちらチェックしてみてください!もちろんオープンポジション的に上記に限らず積極採用中です!!!