プロダクト開発の「遅さ」を徐々に感じる要因

# この記事について
## 背景
先日、約4年間所属していたスクラムチームを離脱しました。
このチームは [よいチーム](https://qiita.com/hishida/items/8415638b60d0cba9f709) だったのですが、開発していたサービス（＝プロダクト）についてふりかえると、以前のようにすばやく機能追加できていないと感じるようになっていました。
プロダクトオーナーも開発メンバーも、なんとなくみんなそう感じていたのではないかと思います。

そのような「遅さ」をなぜ感じるかを考えてみたところ、要因がいくつもあるように思えました。
また、それらは過去の **別のサービス開発でも同じことが言えた** のではないかとも思えました。

「遅さ」の捉えかたによっては、**開発メンバーのスキルのせい** にされてしまったり、**エンジニアの評価が下がってしまう** ような事態も起こりうるのではないかと思います。
複合的な要因があることを知り、チームやプロダクト開発 **全体でどう対策を取るか** を考えられるとよいなと思い、今回まとめてみました。

## 狙い
- サービス・プロダクト開発が進行するに伴って「遅さ」を感じるようになる要因がいくつかあることを知る
- 開発の進行やサービスの拡大に伴い、**自然に起こる** ことを知る
- 開発メンバーのスキル不足だけではない・**誰かだけが悪いわけではない** ことを知る
- これらを知ることで、状況を正しく把握し、（プロダクトオーナー含めた）**チーム全員で対策を考える** ことにつなげたい

# 「遅さ」を感じる要因
:::note
- 機能数の増加
- ユーザーの増加
- データ量の増加
- 考慮事項の増加
- 機能の肥大化
- 手作業運用負荷の増大
- アーキテクチャ・設計のアンマッチ
- 未知の事象の増加
:::
それぞれをこの後詳しく見ていきます。

## 機能数の増加
サービス・プロダクトが進化していくとともに、機能も増えていきます。

次の新機能を作るとき、影響範囲を調べる対象が増えます。
実際に **影響がある機能** も、ある程度機能数に比例して多くなります。
機能どうしの組み合わせも多くなり、**組み合わせた際の考慮事項** や、**組み合わせた場合の障害** が多くなります。

もちろん、機能どうしの依存度をできるだけ下げる設計も必要です。
しかし、当初想定できていなかった影響が後からわかったり、機能追加を繰り返しているうちにいつの間にか依存度の強い部分ができていることも、よくあることだと思います。

また、機能が多くなることで、必要なテストも多くなります。
**テスト仕様** や **テストコード** が複雑化し、**テストの実行時間** も増えます。
テストを自動化している場合でも、実行に時間や料金がかかりすぎてしまい、**実行方法やテスト項目の見直し** が必要になってくる場合があります。

## ユーザーの増加
サービス・プロダクトを成長させるために、ほとんどの場合はユーザー数を増やすことを目指すはずです。
（一般に公開しているサービスでは特に）ユーザーの増加に伴い、使用環境も多様化していきます。
**環境の差異による不具合** の件数も、環境の多様性にある程度比例して増えていきます。
それに伴い、**サービスへの問い合わせの対応** が増えたり、**不具合に対応する/しないの判断をする回数** も増えます。

## データ量の増加
ユーザーが増えたり使用量が増えることで、サービスとして保持しているデータも増えます。
データが増えるにつれ、取得・更新・結合などの **データ操作** に時間がかかるようになってきます。

もちろん、最初からある程度のことは想定してデータ設計をすると思います。
ただし、ユーザーの使用状況や機能追加の方向性など、最初には想定していなかったことが積み重なることで、当初のデータ設計がマッチしなくなってくることも、よく起こるのではないかと思います。
また、データが少ない時には想定しきれず、多くなってきた時に見つかるものもあります。

つまり、最初からすべて想定するのは難しく、いろいろと想定しようとすると立ち上がりがどこまでも遅くなってしまいます。
一方で、データ量が多くなってからデータ設計を変えようとすると、データの移行がとても大変なことがわかり、これを理由に諦めることも多いと思います。

## 考慮事項の増加
サービス・プロダクトの開発に伴い、様々な障害や問題が起こり、対処していきます。
これらの活動を通じて、チームは学びを得ていきます。
次の機能開発などでは、同じ障害や問題を起こさないよう、**気をつけるべきポイント** が増えていきます。

この「学びを得て次に活かしていく」プロセス自体はよいことなのですが、やることが増える傾向はあると思います。
機能開発時のチェックポイントを増やすだけでは、やることが増えていき、各機能が完成するまでに時間がかかるようになってしまいます。
学びは活かしつつ、やることは増やさない方法を少しずつ検討していく必要があります。

## 機能の肥大化
前述と類似しますが、チームが学びを得ていくことで、新しい機能を作るときに **「完璧にしたくなる」** または **「片手落ちが許容できなくなる」** 気持ちになってきます。

この背景には、いくつかの要素があると思います。

- これまでと同じ障害を発生させないようにしたい
- 既存のあらゆるユーザーに影響がないようにしたい（ユーザーが増えると、考慮するバリエーションも増える）
- ユーザーが違和感を感じないようにしたい（問い合わせ対応のコストにつながるから）
- 周辺で見つけた記載ミスや小さな不具合は忘れないうちに対処したい

こうして、 **機能を完成させるハードルが少しずつ上がっていく** ことも、よくあるのではないかと思います。

この肥大化を防ぐために、**完成の定義や受け入れ基準を厳格に定義する** 方法もあります。
ただ、その場合は以下のようなことも起こりえます。

- 共通の「完成の定義」の基準を高くしたくなる
　→全体的にやることが増える
- 新しいPBI（＝プロダクトバックログアイテム）の定義を作ることに時間がかかる
　→プロダクトオーナー、またはPBI作成者の負荷が増す
- 元々のPBIの受け入れ基準に含まれていない要件を、別のPBIに切り出すのにも手間がかかる
　→元々のPBIでついでにやったほうが、手間がかからないように感じる

機能の肥大化は防げるかもしれませんが、逆にやることが増えたり管理が煩雑になってしまうことも考えられます。

## 手作業運用負荷の増大
サービス利用上の手続き・問い合わせ等の運用・リリース作業など、最初は **一部を手動で運用** し始めることもあると思います。
こうした作業の負荷は、サービス拡大に伴い、徐々に増えていきます。
徐々に増えていきますが、慣れていく感覚もあるため、全体の作業の中でのボリュームを意識しづらくもなります。

また、これらの作業をシステム化・自動化するには、ある程度のボリュームの作業が必要です。
ある程度ボリュームがあるからこそ、最初はすばやいリリースなどを優先して手動にしたという経緯があったりもします。
それゆえ、時間をかけてシステム化・自動化する判断にはなかなか踏み切れないケースも多いように思います。

## アーキテクチャ・設計のアンマッチ
サービス・プロダクト自体や周辺状況の変化によって、最初に決めた **設計やアーキテクチャがマッチしなくなってくる** ケースがあります。
これも先述のデータ設計の話と類似していて、最初からすべてを想定するのは難しいです。
また、後から変えようとしても、こちらも考慮事項が多く大変なことがわかり、諦めてしまうことも多いのではないかと思います。

## 未知の事象の増加
チームやサービス・プロダクトを取り巻く状況の変化に伴い、チームが **知見を持ち合わせていない課題** も多くなります。
チーム立ち上げ時や新メンバー採用時にある程度スキルセットを想定してメンバーを集める場合もありますが、将来の未知の事象すべてを想定できるわけではありません。

エンジニアとして個々で技術力向上の学習をしていても、チームが直面する課題にダイレクトに適用できるような知識をたまたま学習している可能性は限られるのではないかと思います。
技術要素や技術観点は多岐にわたるため、学習することの選択肢は多いです。
また、個々で学習する内容は、個人の興味やキャリア指向など、チーム外のことが起点になることも多いと思います。
それがたまたま当たることを過度に期待することも、当たらなかったことを「勉強不足」と断定することも、ちょっと違うのではないかと私は思います。

チームとして課題があり、そこにスキルの獲得が必要なのであれば、**チームで必要な学習を計画する** べきだと思います。

# 対策を考える
ここまで、いくつかの「遅さ」の要因となりうる課題を挙げてみました。
開発初期にサクサク試作してリリースできていた思い出と比べて、足が重くなってきたと感じることは、ほかのチームでも起こりうるのではないかと思います。

しかし、これらの対策を考えたとき、「この課題にはこれをやればよい」と言えるほど、**対策は簡単ではない** と思います。
チームやサービス・プロダクトの状況により、どれを優先すべきかも異なります。

また、いずれの対処をするにしても、規模がかなり大きくなるかもしれません。
より小さく始められる改善はないかを考えるのにも、時間がかかるかもしれません。
場合によっては、一度立ち止まり、機能開発とどう優先順位をつけて進めるかをちゃんと計画する必要があるかもしれません。

まずは状況を洗い出し、**チームで認識を揃える** ことが重要だと考えています。
誰かが悪者になったり誰かが善意で対応するのではなく、みんなで見えるようにして対策したほうがよいと思うからです。
そのうえで、どこから手を打っていくかをみんなで決めていくのがよいと思います。

----
最後までご覧いただき、ありがとうございました。
ほかのチームの方にもご参考になれば幸いです。