概要
株式会社ドワンゴ NFC事業プロジェクト VP of Engineering の @chiyoppy です。
この記事はドワンゴアドベントカレンダーの 22 日目の記事です。昨日は @hiraike32 さんが「Android アプリをマルチモジュールにしたときのCI環境を整える」として、N 予備校 Android アプリの CI について投稿されました。
さて、本日は2022年1月にリリースした「Sheeta」「ニコニコチャンネルプラス」において、開発体制の刷新を行うことでサービスの品質を改善した軌跡をご紹介します。開発会社が参画するプロジェクトでは、コストとスケジュールは契約や見積もりによってある程度のコントロールが可能です。しかしながら、品質のコントロールは困難で、サービスの安定性に課題があったり、いわゆる技術的負債が生まれたりすることがよくあります。
今日は、開発会社に発注する場合であって、開発会社の内部で努力してもらうことによる品質管理ではなく、品質管理の体制と改善のプロセスを適用することで、品質改善が可能なことをご紹介します。
サービスのご紹介
ひとつのシステム基盤で複数のブランド展開を行っています。ひとつは「sheeta(シータ)」と呼ばれる、高度なデザイン管理機能やファンとのコミュニケーションが可能なファンクラブです。
もうひとつは、「ニコニコチャンネルプラス」です。
企画・開発体制
本サービスは、外部の(資本関係がない)開発会社で設計・開発を行いました。ドワンゴには多数のエンジニアが在籍していますので、内製するという選択肢もありましたが、リソース調整の都合やリスクを総合的に判断した結果、外注することとなりました。
ご存じの方も多いかとは思いますが、ドワンゴでは内製開発が主体です。ニコニコ動画も、ニコニコ生放送も、ニコニコチャンネルもすべて内製です。過去外部の会社での開発は小さなサービスではいくつかありましたが、この規模のシステムを外部の会社で設計・開発するというのはチャレンジでした。
私は VPoE(旧 開発責任者) として、このサービスの開発が始まったタイミングでプロジェクトに参画しました。
サービスリリースまでの品質保証体制
前提となる、サービスリリースまでの品質管理体制についてご紹介します。
開発を行った開発会社の他、品質保証を行う別の会社にも入っていただき、品質保証の体制を構築しました。品質保証会社には、正常系のテストケースを網羅的に実施していただきました。また、社内のディレクターを中心に準正常系・異常系を探索的にテストする体制で実施しました。テストフェーズには開発当初に想定していた期間よりも短い時間しか使えませんでしたが、それでも大きな問題が出ないように、リリースまで準備を行いました。
テストで見つかった課題については、優先度をつけた上で修正に取り組み、影響が大きい問題を解消した上でのリリースができたはずでした。
しかしながら、実際には多くの問題をユーザーさま、コンテンツプロバイダーさまからご指摘されただけではなく、サービスを運用するにつれて「この画面が使いにくい」などの新しい課題が、日々生まれるような状況となりました。このとき発覚した問題については、開発会社が精力的に取り組んでくれましたが、サービスマネジメントの観点で、品質保証体制を見直すきっかけとなりました。
サービスリリース直後の開発体制
サービスリリース直後は、リリース前の体制をそのまま引き継いでいました。
当初は請負での開発だったので、やり取りは開発会社の責任者を経由して行っていました。バグを修正しつつ、日々変わる開発状況の把握と、デプロイスケジュールの調整を並行して行うことは非常に難易度が高い業務だったと思います。業務負荷の観点から、責任者にすべての情報を集めるのではなく、複数の人間に責任を分散する必要性がありました。
サービスの規模がある程度大きく、開発と運用の両面からの整理が必要なため、そもそも責任者が全体を把握するという構造に無理があることは明白でした。このため、分割統治の考え方を取り込みつつ、企画〜開発のプロセスを改善する必要がありました。
また、デプロイなどのスケジュール調整のコストが非常に高いことも課題でした。このため、「開発のリズムをつくる」ことが求められました。頻繁なスケジュール調整はそれ自体が高コストなだけではなく、最新のスケジュールに合わせて動き方を変える必要が生まれてしまい、これは無理な計画になったり、作業がない無駄な時間が発生したりする原因となります。
そのほか、コストを予算内に抑えることと、スピードを担保することも必要でした。
開発体制の変更
この状況を抜本的に改善するために、開発体制を見直しました。具体的には、分割統治と職能横断型のチーム編成を通じた「アジャイル/スクラムの導入」です。
まずは、改善後の全体像をご紹介します。インフラチームを除く各チームは職能横断型のチームです。
アジャイル/スクラムの導入
アジャイル/スクラムを導入すべきかは議論がありましたが、課題を整理すると上記の形となるべきだろうという点で合意ができました。導入にあたっては、Scaled Scrum に知見がある方に参加していただいた上で、開発会社と相談しながら進めました。
開発チームの分割 (分割統治)
まず、全体で何となくメンバーごとに役割分担がされていた状況を明確化するため、以下のチームに分割しました。
- Webチーム
- 動画・生放送チーム
- 決済・経理チーム
- インフラチーム
このチーム分割は、ビジネスドメインの境界で行った点を強調しておきたいと思います。これは チームトポロジー (Team Topologies) における「ストリーム・アラインド・チーム」に相当します。
採用されなかった選択肢として、ここでは2種類を紹介します。
まずは「バックエンドチーム」「フロントエンドチーム」といった機能による分割です。ビジネス上の要求は、通常フロントエンドとバックエンドの両方にまたがる要求となります。このため、チームをまたいだコミュニケーションが非常に多く発生する懸念がありました。
また、他の選択肢として、「新規開発チーム」「保守運用チーム」といった分割方法も考えられました。この方法では、ビジネス上の要求にはフィットする一方で、チームをまたいでコードが共有されてしまうという問題が発生します。これもチームをまたいだコミュニケーションが多数発生するだけでなく、コードのコンフリクトが発生することが予想され、不採用となりました。
チームを分割したことにより、何となく全員で全体を見るという体制から、明確化された担当範囲の業務を行うこととなりました。
もっとも、Webチームの範囲が広いと言った問題はあるので、時期をみてまた分割する必要性はあるようには思えますが、以前の混沌とした状況からは大きく改善しました。
チームごとのロールのアサイン (職能横断型のチーム)
また、チーム内に異なる役割をもつメンバーをアサインしました。具体的には以下の通りで、同じチームであっても職能や所属が異なります。このほかは原則として通常のスクラムと同じですが、異なる点として、具体的な作業指示をスクラムマスターから行う点にあります(スクラムマスターには必ず開発会社のメンバーをアサインします)。
- プロダクトオーナー (ドワンゴのディレクター)
- スクラムマスター (開発会社のPMまたはエンジニア)
- アーキテクト (ドワンゴのエンジニア)
- ディレクター (ドワンゴのディレクター)
- システムエンジニア (開発会社のシステムエンジニア)
- エンジニア (開発会社のエンジニア・オフショア先になることもある)
Scrum of Scrum
チームごとの優先度の判断は各スクラムのプロダクトオーナーに委譲されています。ただし、チームをまたいで何かの課題に取り組むこともります。典型的には大きな新機能ですが、バグフィクスでもチームまたいだ変更が必要となることがあります。
このため、全体を統括する役割として「Scrum of Scrum (SoS)」を導入することとしました。
SoS では、他のスクラムチームと同様にバックログの作成・優先度の評価を行います。タスクの見積もりまでは行わず、実際のタスク遂行は担当チームに委譲します。簡単にいうと、タスクの順序づけと分解と担当分けが、SoS の責任範囲となります。
SoS の導入はスクラム導入当初から決めていたため、導入自体の困難さは高くなかったように思えます。
ポイントとしては、各チームのスプリントのスケジュールを合わせる必要があります。あるチームが月曜日始まりの2週間スプリントで、他のチームが水曜日始まりの1週間スプリントだと、SoS を通じたマネジメントが難しくなります。このため、各チームのスプリント開始日と期間は全体で合わせる必要があります。
スプリントのスケジュール
スプリントは(年末年始休暇などを除き、原則として)2週間としました。繰り返しになりますが、全てのスクラムチームで同じ開始日と終了日としています。
そのほか、スプリントの進め方は概ね通常のスクラムと同じですので、詳細は割愛します。
ドワンゴのエンジニアの役割
さて、スクラム開発の体制が整ったところで、ドワンゴのエンジニアの役割を改めて定義する必要がありました。
通常の請負開発であれば、システムの内部の品質評価は、設計等のドキュメントや、その管理体制を対象にして行うことが多いように思えます。ただし、サービスを長期的に運用すると考えたとき、この方針は本当に最適なのでしょうか。
ドワンゴの内製開発では、ドキュメントそれ自体よりも、エンジニアが主体的にコードベースをメンテナンスする姿勢や、設計レビューやコードレビューといったチームでの活動そのものを重視します。この考え方をベースに、開発会社とのコラボレーションを推進していく、というのがゴールになります。
ただしこれではあまりに抽象的なので、ここではサービスの品質をブレイクダウンして、設計の品質とコードの品質のふたつの観点で簡単にご紹介します。他にも運用の品質や、サービス仕様自体の品質(矛盾の解消など)について考える必要がありますが、執筆の時間の都合で割愛させていただきます。
設計の品質担保
設計の品質評価は、主にドキュメントがその評価対象となります。
設計ドキュメントでは、最終的に選ばれたアーキテクチャが記述されます。しかしながら重要なのは、そのアーキテクチャが選ばれるに至った経緯です。なぜ他の選択肢を排除したのか、実装されているものの他にはどんなアーキテクチャを検討したのか。こうしたドキュメントは、将来の設計変更時に役立つことが経験的に知られています。
さて、この設計ドキュメントの作成や評価には、エンジニアの専門性が必要です。
このため、各チームにアサインされたアーキテクトに対して、アーキテクチャ上の判断について責任をもつことを求めています。アーキテクトは、設計上の選択肢の確認や、将来的な設計変更が必要な可能性にも配慮した上で、迅速に結論を出す必要があります。
この成果は一部で出ており、たとえばユーザーの決済状態に応じた処理は、(煩雑ではあるものの)サービス仕様としての整理だけでなく、データベースの状態との対応関係を明確にできました。
ただし設計の成果物としては十分なものが揃いつつあるものの、そこまでのプロセスはやや混沌としています。この点はまだ改善が必要で、まだ最終的な結論は出せていませんが、Architectural Decision Records のようなものの導入を想定しています。
また、技術的負債のパラメータのひとつは将来の追加機能(要望)ですので、アーキテクトは、将来どんな機能が求められるかをロードマップを踏まえて認識しておく必要があります。
ともかく設計の品質という観点では、よりしっかりしたアウトプットを作ることをゴールにしつつ、そこまでのプロセスやモチベーションにフォーカスして取り組む必要があるように感じています。誰がレビューしたからとか、レビューした回数は関係ありません。ドキュメント自体の改善に集中しやすいプロセスを、各チームの状況やメンバーの特性を踏まえて整備する必要があります。
コードの品質担保
コードの品質を担保しようと考えたとき、まず取り組むべきはコードのレビューです。
開発会社やそのメンバーは、直近の開発を完了させることにフォーカスします。このため、ていねいなコーディングよりもスピードを優先したいというモチベーションが(人にはよりますが、一定程度)存在します。
また、コーディングの一部はオフショア先(海外)で実施しています。コーディングスキルでいうとオフショアの開発者も国内の開発者も大きな差はないように思えますが、意志疎通や課題に対する解決策の精度の点では不安があるのも事実です。
一方で、サービスとして継続して運用・改善していくという観点からは、いわゆる「良いコード」であることが求められます。すなわち拡張に対して開き、変更に対して閉じていたり、モジュールの凝集度が高く、モジュール間の結合度が低くなっているなどの特徴を備えているということです。
このため、各チームにアサインされたアーキテクト(エンジニア)に対して、各チームで管轄するコードを深く網羅的に理解し、コードの品質を維持・改善するために具体的なアクションを取ることを求めています。
コードの品質は(ある程度)定量的に判断する手法もありますが、成長しているサービスでは、時間とのバランス感覚も求められます。良いコードなら何でも良いわけではなく、求められるスピードでデリバリーしなければなりません。
したがって、コードの品質をそれ単体で問題とすることはありません。最も重要なことはビジネス上のゴールの達成であり、低品質なコードはそのゴール達成を阻害するから、品質担保が必要なのだという観点で整理しています。
開発者体験の改善(現在のとりくみ)
Developer Experience チームの編成
内製開発と比べると、今回のように開発会社とコラボレーションするプロジェクトの方が、メンバーのアサインが流動的になります。特にオフショアの開発チームを組み合わせると、この傾向はより顕著になるように思えます。
また、開発会社や業務委託がメンバーとして入る場合、加わるメンバーが開発に慣れてパフォーマンスを発揮できるようになるまでの時間は個人差が大きいです。
毎月新しいメンバーが入ってくるプロジェクトでは、毎月の開発工数の一部がプロジェクトの開発ルールの習得に消費されます。このため、メンバー構成が(相対的に)安定している内製開発と比べて、よりプロジェクト参加時のコストを小さくすることの効果が大きくなります。
また、オンボーディングのコストが低減できたとしても、習熟したメンバーが離れることによる損失は無視できません。したがって、開発会社も含めて、メンバー自身に「このプロジェクトから離れたくない」と思ってもらえる、いわば「DX 温泉」を作る必要があります。(DX "沼" というアイディアもありましたが、自ら希望して入ってきて抜けられなくなるところをゴールにおいて、"温泉" という表現になっています。)
そこで、オンボーディングだけではなく広く開発者体験を改善することを目標に、Developer Experience(DX) チームを編成しました。
DX チームは、直近だとブランチ戦略の見直し、デプロイプロセスの改善、開発ルールの整備と全体展開、開発者向けツールの作成といった業務を行っています。中長期的には、下記 DX Criteria を参考にしつつ、プロジェクトの開発者体験の今と目指す姿のギャップの把握や、プロジェクト全体への貢献度を測定する KPI の整備に取り組んでいければと思います。
(参考) DX Criteria|日本CTO協会
https://dxcriteria.cto-a.org/
Developer Experience は主に内製開発のシーンで活発に議論されているように思えます。私の考えでは、長期的な関係性を前提にできなくても、ルールを整備することでソフトウェア開発ライフサイクルを良い状態で維持するという意味で、開発会社が参加するタイプのプロジェクトでもその価値はより大きなものになると思います。
まとめ
「Sheeta」「ニコニコチャンネルプラス」の事例をもとに、アジャイル/スクラムの導入によって開発体制に秩序ができたことを確認できました。また、開発会社で開発する場合であっても、社内のエンジニアが設計とコードレベルでの品質担保を通じて、大きな役割を果たしていることがお伝えできたかと思います。
今後もビジネスの成長にあわせて(時には先行して)システムの改善が必要になります。特にスケーリングの課題が出てくるのは来年以降になるかと思いますので、こういった難しい課題に取り組める開発体制ができたことは素直に達成感があります。
明日のアドベントカレンダーは @kadoyau の担当です。楽しみです。
最後になりますが、本プロジェクトに関わったすべての方に御礼申し上げます。