今年話題になった開発生産性について、品質と絡めて徒然と考えてみた

本記事はソフトウェアテスト Advent Calendar 2022 2日目の記事 **となるはずだった記事** です。原稿落としてしまって申し訳ございません！！
そしてゴリゴリ書いてる途中で気付きました。「これ、t_wadaさんが言ってる『[質とスピード](https://speakerdeck.com/twada/quality-and-speed-2022-spring-edition)』そのまんまじゃん！」って。せっかく書いた記事の供養のため、このまま投稿させてください…。

# 今年の気付き + この記事で言いたいこと
ここ2～3年、開発生産性(developer productivity)に着目して取り組んでいる企業さんがとても増えてますね。今年のデブサミ2022夏のテーマは 「[アジャイル・DevOps時代のプロダクトとエンジニア組織を支える、Developer Productivityへの道](https://event.shoeisha.jp/devsumi/20220721)」 だったことからも、かなりホットな話題だと思います。このテーマ、事前に知ってたら聞きに行ったのに！興味深いのが、一昔前まではSREしかやってなかったようなことをQAの人達がやり始めてることですね。

時期同じくして、7/27(水)に行われたオンラインイベント、「 [リーダブルなテストコードについて考えよう](https://veriserve-event.connpass.com/event/243280/) 」が大盛況でした。QAのイベントでは珍しい、事前登録者数1000人超え。どの講演もマジでめちゃくちゃ楽しかった。 ~~なぜ私の飲酒日である水曜日に行われたのか。~~ "非エンジニアでも読めるような、人間が使う言語(自然言語)に出来るだけ近い形で書かれたテストコードを書きましょう"ということが、上記イベント内から私が学んだことでした。名前でも付けて広めていきたい考え方ですね(軽くググって出てこなかったのですが、IaCにもじって **ドキュメント AS テストコード** なんてどうです？)。

で、最近考えたのですが、
- 品質を保つことって、開発生産性を維持する上でとても重要なのでは？リーダブルなテストコードを書くことって、開発エンジニアにとって必須のスキルなのでは？
- 品質の必要性をビジネス側に伝えるのに、開発生産性の話を持ち出した方がウケが良いのでは？
- この技術を含め、QA界隈に伝わる技術を開発生産性の向上に活かしていきたい。

と考えたりしたので、その話題を書きたいと思います。

# 品質と開発生産性の関係性の考察
## レガシーシステムの開発・保守の経験から学んだ、保守性を低下させるアンチパターン発生例
今手掛けてるシステムが一部レガシー化していて、何故保守性が低いのかを振り返りました。下記例は、事実とフィクションが半々くらいです。

### レガシーシステムへの新規実装
t_wadaさんの講演&テストコード見てると、回帰テストが失敗するようなパターンが出てきて、「あぁ…テスト駆動開発かくあるべし」と思いますよね。こうやってテストコードを書きながら開発してきていれば怖くないのに、実際はテストコードがないレガシーシステムの保守メンテをしなきゃいけなかったり、下手したら今も(テストコードを書かずに)レガシーシステムが生み出され続けているのが現状です。

そんなレガシーシステム開発あるあるなのが、"既存コードに影響を与えないように実装する"ということです。テックリードを含む普通レベル以上の開発者なら、新規開発と共に既存箇所のリファクタリングも検討すると思いますが、システム開発を知らない方々からすると、「条件分岐を追加すれば既存に影響でないでしょ」と考えがちです。ジュニアレベルの開発者もまた、新規要件が出てきた際は、大抵はリファクタリングを考えず、分岐噛ませて、新規機能開発するでしょう(しかもクラス設計せずに)。例えばこんなように。
```diff
前の処理

- 処理A 50行くらい
+ if パターンAだったら
+     処理A 50行くらい
+ elif パターンBだったら
+     処理B 50行くらい

後の処理
```

2分岐くらいならまだ許せますが、新規要件が出てきては追加開発、追加開発、追加…とやっていくと、最後はこんな感じになってます。

```
前の処理でうんだらかんだら

if パターンAだったら
    処理A 50行くらい
elif パターンBだったら
    処理B 50行くらい
elif パターンCだったら
    処理B 50行くらい
elif パターンDだったら
    処理B 50行くらい

(後続処理で条件追加)
if パターンCだったら
    処理C' 50行くらい

(更に後続処理で条件追加、かつ他人が見たら意味不明な条件になってる)
if パターンBで◯◯だったら
    処理B' 50行くらい
```

こうして、見通しの悪く、not DRYで、低凝集で、数百～数千行ある神処理が出来上がりましたとさ。こうなるとリファクタリングは困難です。というかコードを見るだけで、あまりの醜さに吐き気を催すようになります(実体験)。

### レガシーシステムの保守の仕方
上記のようなレガシーシステムは、チームへの新規参入者の障壁となります。何故その処理をするのかがわからないので、コードを読んでも正しいのか正しくないのかが理解できません。こうなるとチームがシステムを安全に保守し続ける方法は一つしかありません。機能毎に担当者を割り振り、 **(読み解けない既存コードではなく)属人化させた運用によってシステムの冪等性を保証する** 他無いのです。ここまで来ると祈祷と何ら代わりはないですね。
機能毎に属人化させるので、新規参入者もまたどこかの機能の担当となり、チームから外せなくなります。こうしてチーム増員による人的コストは増大し、それに伴って膨れ上がった保守コストは削減できず、そして新規開発する空きリソースは減っていくことになります(書いてて思ったけど、まるで銀英伝に登場する、"攻勢限界点に近づく部隊"を見ているかのようだな)。そして新規開発が出来なくなるほどがんじがらめになって初めてみんな気付くのです、「どうしてこうなった…」と。

## 上記経験から、品質と開発生産性について考察してみた
### 保守性を維持してこそ開発生産性も維持される(が、まだまだ認知が足りない)
(この辺書いてる辺りでt_wadaさんの講演を思い出して資料を改めて読み直して、)『[質とスピード](https://speakerdeck.com/twada/quality-and-speed-2022-spring-edition)』には、結論のページに以下の記述があります。
> 「品質」の名のもとに犠牲にされるのは内部品質の特に保守性(テスト容易性、理解容易性、変更容易性)

上記の例を見ても、全くその通りだと思います。特にコードの理解しやすさ、コードの変更のしやすさについては、上記コード例は酷い有様と言わざるを得ません。特に既存処理に修正を加えないといけなくなった場合は最悪です。至る所に同じ処理があるため修正漏れが発生したり、デグレードが発生したりするでしょう。
面白いことに、上記コード例のようなレガシーコードを見ても、低保守性に気付かなかった開発者も少なからずいました。新規開発依頼を受けてきた歴史の通りにコードが書かれている事自体が、現状のコードに正統性を与えて、低保守性であることが見抜けないようでした。「これまでこういう依頼を受けてきたんだから、こういう分岐になってて当然じゃん」と考えたようですね。しかし、PJが歩んだ歴史とコードの保守性は全く別物です。理解や変更に痛みを伴うコードではなく、条件が整理されて過不足がない簡潔なコードでないと、迅速なデリバリが果たせなくなります。

#### コードの保守性を高めるためにQA部門は何が出来るか
個人的に不思議なことなのですが、様々な会社さんに対して開発部とQA部の守備範囲・棲み分けについて聞いてみると、 **"開発部はプロダクトコードとユニットテストコードを担当し、QA部はAPIテスト以上を担当する"** というパターンが多いなという印象を受けました。開発者がコードに対して責任が持ち、QAは仕様を満たしているかをチェックする組織が多いようですね。しかしながら、"非エンジニアでも読めるテストコード"がリーダブルテストコードであるならば、QAこそ率先してテストコードを読む必要があるのではと思います。テストコードが読めて開発者に詳細設計を口出しできるというのはハードルが極めて高いのかもしれませんが、プロダクトコードやテストコードに対して様々な人の目を通すことこそ、保守性を高めていく最良手なのではと考えています。

### 保守性を高める作業工数の要求において、ウケが良い話とは？
この話をまとめるようになったきっかけの記事があります。少し長いですが引用します。

> 一定以上の複雑なソフトウェアでビジネスを作る事業なら、アジャイル開発で使われる実装速度の目安である「ベロシティー」や、場合によってはコードベースに対する数カ月分のコミットログを見たほうが良いのではないか
> (中略)
一定規模の組織で開発するようになった段階であっても、技術的負債が蓄積したり、初期のアーキテクチャー設計がまずかったり、選択した技術スタックのエコシステムが停滞するなどすれば、機能拡張の速度はどんどん落ちて行くこともあるでしょう。どんなに瞬発的開発力があっても、土台がぐらつくと速度が落ちることがあるため、一定規模以上のチームになってくれば短期の「スプリント」と長期の「マラソン」に分けたアプローチも大切になってきます。
> (中略)
> 上に書いたようなことは、本当のところシード・シリーズAなどではバリュエーションに影響を与えて良いことなのではないかと思っています。
> cf: [スタートアップには「開発速度プレミアム」もある | Coral Capital](https://coralcap.co/2022/11/speed-of-software-development/)

開発者やPjM, PdM, 経営層だけでなく、投資家もまた開発生産性について着目し始めている(あるいはとうに着目していてそれを明言する)時代になってきています。これまで見てきたとおり、品質(保守性)が落ちれば開発生産性も落ちることがわかっているので、"顧客に提供する価値の保証"としての品質よりも、"開発生産性を持続させる要因"としての品質という観点から話したほうが、ステークホルダーを説得しやすいのかなと思いました(少なくとも私だったらそちらのほうがしっくり来る)。

### QA界隈に伝わる技術を開発生産性の向上に活かす
私にとってこれが今一番興味関心あること。西先生が提唱されてる [QMファンネル](https://www.slideshare.net/YasuharuNishi/quality-management-funnel-3d-how-to-organize-qarelated-roles-and-specialties) により、従来SREがやっていたようなCI/CDパイプラインの構築やテスト自動化は、パイプラインエンジニアが担うように一部の企業でなりつつあります。せっかくこれまで開発畑を歩んでこれたので、これからは品質の知見を開発者へ還元する"品質エヴァンジェリング"をしながらパイプラインエンジニアとして動くことで、開発生産性を最大限に高める動きをしていきたいなーと改めて考えた2022年でした。