スタディサプリ Product Team Blog

株式会社リクルートが開発するスタディサプリのプロダクトチームのブログです

入稿devsチームで、校閲PDF出力機能のリニューアルをおこなった話【2/2 振り返り編】

こんにちは、スタディサプリで開発をしている @motorollerscalatron です。

前編では、「入稿」「校閲ドメインの発足からサブチームへの切り出しと、校閲出力サービスのリニューアルのエピソードを技術的観点を交えながら共有させていただきました。この後編では、プロジェクトが完成しきった時点での自身の省みを中心に共有させていただきます。

今回の案件で、問題解決に対して大事だと感じたこと

知識をもっている人をうまく引き込むためには、質問は端折らない

今回の作業では、結果、私自身はメインで開発をしつつも、フロントエンド部分であれば @indigolain さんとは定期的にペアプロを組んでもらうようにしました。 @indigolain さんはチームとしても近く、今回ある程度リソースを割いてもらうことも合意していたので、ペアプロのペースはスケジュール感を持ちつつも、ある程度質問の切り口をフランクな形で伝えることができました。

一方、コンポーネント実装後の実際のマイクロサービス化については、複数メンバーのいる SRE へのグループとしてのメンションから始めて、どういったテンプレートが参考になるか、をきくところから始めていきました。開発部内のリポジトリは、基本的に開発メンバーであれば他の PJ のものも見られるので、新しいサービスを作るときには、特に、社内に似た事例を持っているかをコード検索で調べていくことができます。一方で、実際のやりたいことに対する正解、というのは必ずしも過去例が既にあるとも限りません。

確かに、新規にマイクロサービスを立てるときに共通で必要になるようなテンプレート的な設定があるので、ある程度のアウトラインは見えていたとも言えます。そうやってチェックリスト化できていたものについては指示をうけつつファイルを揃えていくことができたものの、前編で述べたような新しい設計にしたことで、自分でも気がつかないうちに、他の既存サービスにはないようなイレギュラーな面も出てきていたことが、SRE とのコミュニケーションの中でわかってきました。

この時、(自分の近くにいるメンバーでなく)もう一つ外側にいるメンバーとでは、少し伝え方のニュアンスに注意が必要だということを悟りました。というのも、私は自分の想定の部分で、 ここは既存の設定の焼き直しでできる、と思い込んでいた のですが、SRE には自分が新しくやろうとしていること正確に伝えられていない/確認ができていない状態で、仮説でできると思った延長で先に「こういう設定をしてほしい」というコミュニケーションを始めてしまっていたのでした。

一般的に、自分の一つ外側の集団に属する人に質問をする、というのはきく側・きかれる側、双方に内輪でのコミュニケーションより大きいコストが見込まれると考える傾向があると思います。開発の後半での特にサービス間通信を含んだような疎通確認や、新規で書いたインフラ部分の設定の作業では、コミュニケーションの最初に先にやりたいことをクリアに伝えていられるとよかったんだな、と感じました。

質問をなるべく小さくしようとして、若干端折ってしまいがち

私は、自分で調べていくと(中途半端な好奇心が先走ったり、それぞれ別の担当業務を持っているであろう開発グループの集団心理を変に推測してしまったり、で)、自分で前もって調べている量が多ければ多いほど、相談相手にとってコストが少なるかのように思い込んでしまいます。今回の開発の後半フェーズでは、PR ごとに push 後の CI を通してしか確認ができないものがでてきたり、中には SRE 側との密な連携をしながら先に進めていく必要のある作業が出てきていました。この時、質問時に伝えているもともとやりたかったこと、がわかりやすい形で残っているかどうかで、結果、継続的なコミュニケーションの質に大きく差が出てきました。

上の slack の例は、いつもお世話になっている SRE @kyontan さんに、ついつい先行して伝えた情報の鮮度などを垣間見ずに書いてしまったと思っているもので、この後 PR は少しずつ完成して進めていけたのですが、エラーの内容自体がうまく理解できてないのに、それを要約して伝えようとしてしまったのですが、結果、そこで質問に質問を被せる形のコミュニケーションを生み出してしまうこともありました。

伝わりにくかった部分を端的に切り直して質問を書き直してみた例

これは、スレッドのメッセージ数が3桁ぐらいになったところで、最初に言おうとしていたことを、改めて別のフォーマットで同じ質問をした例です。 ご存じ @chaspy さんの誘導もあって、私も改めて最初の前提として伝えたかったのかが、この3つであることに気がついたのでした。文章の長さは同じくらいですが、質問を受け取る側として、どのあたりに回答を期待しているのかの感じ方には、大きく差が出るはずです。 (本当のところは、同じスレがずいぶん受け答えで追いづらくなっていたので、当時 @kyontan さんの ボスであった @chaspy さんがいいタイミングでヒントをくれた感じです)

結局、このやりとりの中で、 tara-content-data (前編の説明で出てきていた、「学習画面問題コンテンツ」のリポジトリ名) へのアクセスには、このサービス専用の GitHub Apps を用意するのが最適だ、という結論にたどりついたのでした。私自身は、今回のサービスは既存で同じアクセスのパターン(と思い込んでいて)既存の github token の利用を前提として実装をしたままだったのですが、 その妥当性をSRE に確認するのを遅延していたのを、すっかり忘れていたのでした。

ペアプロと壁打ち

Next.js の SSR や、GitHub Apps 等を利用する部分などを含めて、今回の開発は、「自分は使ったことがないのだが、識者の云うことによれば、これでできるはずだ!」を1つ1つ証明しながら進んでいくような、不確定要素が大きい開発でした。 識者とのペアプロは今回も何回もお願いをしていた中、(ペアプロ、モブプロ自体については、私は以前に記事化 させてもらっているので、気になる方は、そちらを是非参照下さい。)、開発メンバーは、皆、並行して業務を持っているのので、全く理想通りに時間を合わせられるとも限りませんでした。そんな時は、担当者でないようなメンバーとの壁打ちも有効に活用しました。

私は、思い込みが強くて、ふと時間がたつと仮定を残したまま調査に踏み切っていることを忘れて、Google 検索で文字列的なマッチ度の高いものを見ては、「世の中に、いかにも今体験しているのと近い現象があるじゃないか」→「これが怪しい!」と短絡的に因果関係を推測したものを、そのまま共有して騒いでしまいがちだという自覚があります。そして、この共有した瞬間は、覚えていた仮説と検証済み部分の境界を、時間がたつとともに、いとも簡単に忘れてしまいます。

日々の業務では、どうしても時間的な制約ときりのいい報告の単位がある以上、不正確な部分を全て排除するまで報告を遅延する、というのも現実的ではないでしょう。ある程度のわだかまりは含んだまま、それは「ある程度わかりやすい話の流れにした状態で、まわりの人に打ち明けたほうが話の入り口としては入りやすいのでは?」と思う自分も中にいて、細かいニュアンスを伝えるのはいったん人を引き込んでしまわないと、先に進めない。そんな時、「どこまでが試した組み合わせか?」「影響する因子は洗い出せているか」など見直すには、ほどよく自分に近いチームメンバーとの壁打ちを利用すると良い、ということを、より実感しました。

これは壁打ちの相手は、必ずしも前提などを知っているかどうかは、あまり気にしません。それよりかは、自分の考えの抜け穴などを、側で聞いてもらって、指摘してもらったり(時には自分で話している段階でおかしいと気づくことすらあります)することを狙っているので、時には自分と思考回路のパターンを辿らないよう、あえてその案件をあまり一緒に見ていない人がよかったりします。後半、Next.js による実装部分が完成したあとは、 @indigolain さんは本来の所属プロジェクトのほうに専念することになっていたので、私は今までのような壁打ちの相手を失っていました。そんな時、チームの相方の @teppei-kitagawa さんに壁打ちをよく依頼しました。teppei さんには、私が今回この校閲出力のリニューアルをしている間、入稿チームの他の色々な開発案件を担当してもらっていて、普段の daily では進捗を伝えたりしていたものの、コードの詳細などを一緒に途中でみてもらうのは、PR レビュー以外のタイミングではあまり行なっていませんでした。それでも、毎回壁打ちをするたびに、自分の見落としていた内容が何かしら明らかになる体験をしました。

壁打ちをする目的は、気づきだと思っています。「これのここを質問したい」と自分が思っている内容自体に対しての直接的な回答ではない部分に収穫があると考えれば、必ずしも今課題と認識している問題範囲でのプロである必要はないと思います。ですので、「ここを知っている ◯◯ さんの手があくまで待つ・・」というよりは、きてくれる人が見つかったら、その人とのセッションを優先しました。スケジュールも必ずしも先に入れるとも限らず、カレンダーの空きを見つけて 直近の日時で予定を送ることもあれば、朝のチームの daily ミーティングで話して、画面共有をそのまま使って延長でコードや VSCode を開く、という導入の仕方で行うこともありました。

少しでも難しく見えてきたら issue を分割・追加/1回で完璧なものを作ろうとしない

今回紹介したリニューアルの開発業務は、入稿 devs というチームの開発タスクの1つとして位置づけた以上、issue 化はもちろん行っていました。 入稿 devs チームでは、他の開発チームと同じように、2週間単位のスプリント開発は踏襲しており、その流れで、issue にはストーリーポイントをふるのは、本件でも変わりありませんでした。しかし、このポイントの見積もりの目的は、規模感の相対的な見積もりであり、途中、チームのベロシティの値としての見え方で時折不安になるものの、実際値が(見積もりから)外れてしまうことには、それほど神経質にはならないようにしました。それであっても、他の案件に比べると、かなり「ここが最大の山場だろう」という報告を何度か繰り返しては、すぐ次に別の問題が構えていることも多かったです。そうした時は、 issue を分割することにしました。

当初、PBI issue の1つとして、この案件を定義したとき、分割 issue は以下の3つにとどまっていました。

  • PDF 出力の設計
  • (実装)校閲出力コンポーネントの作成
  • (実装)刷新版エンドポイントが見にいく Next.js server を動かす

マイクロサービスが独立して立つことは視野に入れつつも、この段階ではこの3つの分け方と、相対的なストーリーポイントの割り振りにとどまりました。

一方、以下は issue クローズ時に結果として出たものです。

プロジェクト終了時点で、結びついた 6 つの issue。3 つ目の puppeteer アップデートなどは、まさか入ると思わず

もともとあった issue とは別に、「puppeteer アップデート(3 つ目)」「選択肢シャッフルが ON かどうか(5 つ目、比較的コードベースの近い改修を、ついでに対応したもの)」などが加えられています。 また、最初の issue 起票で「Next.js server を動かす」としていた issue も、後で2つの issue「Next.js server を動かすための tara アプリケーションの開発(2 つめ)」「Next.js server を動かすためのサービス立ち上げ(1 つめ)」 に分割しました。これらの分割は、想定より大きく掛かってしまっているという心理から、最初は自身ではなかなか気が進まなかったものです。しかしながら、時間の経過とともに、issue のスコープが知らぬうちに膨れていたりするのを見直す上でも重要でした。( Estimate に表示されているポイントは、後から実績値として入れ直したものなので、最初とは規模が変わったりもしました。)

issue分割

また、試行錯誤の多かった Next.js SSR 部分の PR の作成では、アイデアを全て試していいものを採用したかったので、

  • 1つの実験パターンは1つの PR で実装(コミットで詰んで全部表現、とはしなかった)
  • 寿命がある程度長くなったら、部分的なマージができない限りは、いったん捨てる
  • RFC, PoC など位置付けは明確にしておき、スコープがずれないようにする

などの心にとどめながら、少し回り道でも、後から決断の正当性を客観的に保証できるようにしていました。 お陰でなのか、普通、こういった機能のリリースは直後に予期せぬ不具合が出たりしがちで、内心ひやひやしていたのですが、想定した動作レベルで問い合わせもほとんどない状態で、使ってもらっています。

まとめ

以上、今回は前編・後編と通じて、スタディプリプロダクト開発の中でも、ちょっと毛色の変わったドメインの紹介と、その開発の事例について語らせていただきました。また、この記事では、新しいサブチーム「nyuko devs」の紹介を若干兼ねたつもりでもあります。 最後までお読みいただき、ありがとうございました。