見出し画像

「影響範囲の考慮漏れ」によるソフトウェアトラブルの多発はビジネス継続性に対する危険信号

リリースするたびに「影響範囲の考慮漏れ」によるトラブルを起こす。こういう症状は、既存のソフトウェアシステムに追加開発を繰り返す組織によく見られるのではないかと感じます。コードやシステムの変更が影響を及ぼす箇所を見逃してしまい、未修正な箇所が残されたまま本番リリースされたために発生するトラブルです。

このようなトラブルが頻発すれば、関係者らは不満を感じます。エンジニアたちの能力に不信感を抱くかもしれません。

しかし、不満の矛先をエンジニアに向けたところで問題が解決することはありません。そもそも原因を見誤っているからです。根本的な原因は、もっと奥深くにあります。

影響範囲の考慮漏れの多発は、ソフトウェアシステムが大きな問題を抱えていることを知らせるサインです。このサインを見逃して表面的な対策ばかりを続けていると、症状が良くなるどころか、かえって悪化し続けることになるでしょう。


問題/原因の3層構造

まず、「影響範囲」とは何なのでしょうか。ここでは話をシンプルにするために、対象を自社で開発するソフトウェア(アプリケーション)に絞ります。インフラやプラットフォームについては割愛しますが、問題の構造は似ています。

既存のソフトウェアに対する追加開発は、既存のコードに変更を加えるということです。

誤解されやすいところですが、1つの追加開発であっても、変更対象となるコードは1箇所だけではありません。直接的に関係するコードだけでも複数あります。そのうえ、それらのコードが影響して、追加開発の対象となる機能とは直接関係しないコードまで変更する必要性も発生します。また、それらがコードベース内に近接して存在せず、様々に散らばっていることも多いのです。

これが、「影響範囲」と呼ぶものです。

変更対象となるコードを漏れなく洗い出し、正しく変更しない限り、ソフトウェアは欠陥を抱えることになります。追加開発を終えてリリース後に、この欠陥を起因とした本番トラブルが発生する症状が、「影響範囲の考慮漏れ」によるトラブルです。

このトラブルを引き起こす原因は、実は3層で構成されています。表出したトラブルは、最上層である1層目を原因として引き起こされます。しかしその1層目は、2層目を原因として引き起こされた問題であり、2層目は最下層である3層目を原因として引き起こされた問題だという構図です。

これらすべての層に適切な対策を打つ必要がありますが、下層にいくほど問題の存在が見えづらく、また、その対策の難易度が上がるようです。そのためか、対策が1層目や2層目にとどまる組織が多いように感じています。

1層目:影響範囲の考慮漏れ

まずは1層目。ここでの問題は、変更対象の洗い出しにぬけもれが起きてしまうこと。まっ先にこれを止めなければ、トラブルが止むことはありません。

この層での対策は、変更対象の洗い出しに時間と労力を割くことと、本番稼働までに漏れを検出して修正することの2つです。ただしこれらの対策は、リリースまでのリードタイムの悪化という別の問題を引き起こします。

まず、設計を含め、開発に対する見積りが大きくなります。極端なケースでは、従来規模の1.5倍、2倍といったレベルの見積り結果が出されるように。過去の失敗から、分解されたタスクごとに大きなバッファを追加し、相対的に大きく見積もるようになるからです。そうして、変更対象にぬけもれが出ないよう網羅するための時間を確保するのです。

次に、リリース前のいわゆる「テストフェーズ」の期間が長くなります。これも、過去の失敗を受けて、テストケースが大幅に増えるためです。「影響範囲の考慮漏れ」では、リリースした新機能や改善した機能とは直接関係のない既存機能に欠陥が生じることも多いというのが特徴です。つまりデグレです。そのため、人手によるリグレッションテストの網羅性を高めたのです。

当然ながら、追加開発をリリースするまでのリードタイムが長くなります。これまでなら4週間の計画でリリースできていたものが、6週間、8週間かかるようになるため、関係者らは不満をつのらせ始めます。そして、「見積りが大きすぎる」と、開発者らに詰め寄ります。

すると開発者らは、見積もりに多大な時間と労力をつぎ込むようになります。見積りの根拠を示すために、その精度を高める努力をはじめるからです。

これらの連鎖の結果、追加開発のリードタイムはさらに大きくなっていきます。ソフトウェアの外部品質と引き換えに、スピードを犠牲にすることになったのです。

しかし、続く2層目に手を打たない限り、変更対象の洗い出しにぬけもれが起きてしまいやすい状況は変わりません。それが意味することは、1層目の対策をいつまでも続けなければならないということです。

ビジネスの観点から見ても、このままで良いはずがありません。そのうえ、ビジネス責任者と開発者らの間で感情的な対立も生じかねません。

2層目:既存コードが複雑

2層目は、1層目と比べて、開発者以外にはその存在が見えにくく、対策も困難な問題です。それを知るためには、開発現場をもっと深く観察する必要があります。

変更対象を漏れなく洗い出すことは、簡単ではありません。コードベース内のコードをすべて記憶し、理解している人などいないからです。IPAによると、ソフトウェアの改修・保守プロジェクトで扱うコードの行数は22.2千行(SLOC)が中央値です。単純には比較できませんが、文庫小説1冊あたりが数千行程度ですから、コード量の大きさが、記憶できるレベルではないことが理解できるでしょう。

IPA 『ソフトウェア開発データ白書2018-2019』p.92, 図表5-2-24

開発者らは、この広大なコードベースの中から変更対象を洗い出すのです。まずは、いくつか目星を付けてコードを読んで理解し、そこから流れをたどりながら範囲を特定します。そして実際にコードを変更し、その変更による影響を受ける箇所がないかを確認します。影響があればまたそのコードを読んで理解し、流れをたどる。この繰り返しです。また、あとから変更した箇所の影響を受け、先にに変更した箇所の挙動がおかしくなることもあります。対象を漏れなく洗い出し、正しく変更することがいかに難しいことか。

この難易度は、既存コードが複雑なほど高まります。これは、ソフトウェアエンジニアでなければ、イメージすることも難しいかもしれません。

同じ機能を実装するにしても、どのように実装するかの選択肢は無数に存在します。この選択によっては、コードがシンプルになったり、複雑になったりします。そして、複雑なコードは、読み手にとって理解しづらいものです。

これは文章を読むことと似ています。シンプルでわかりやすい表現で書かれた文章は、理解しやすいものです。しかし、同じテーマを扱った文章であっても、煩雑に書かれたものや、複雑に表現されたものは、読み手の理解を阻害します。

もちろん、そもそも理解が難しいテーマを扱った文章を理解することが難しいように、理解が難しい実装にせざるを得ないケースもあります。

このように、「影響範囲の考慮漏れ」の発生頻度を抑えるためには、既存コードの「理解のしやすさ」を高める必要性があるということが分かります。そのための活動が、よく言われる「リファクタリング」や「リアーキテクティング」です。

この2層目への対策は、2つの点で、実行が困難です。

1つめは、「既存コードの複雑さ」という状態が、開発者以外の関係者にとって理解が難しいという点です。ここに理解が得られなければ、対策のために時間を割くことができないかもしれません。

2つめは、対策に時間がかかりすぎること。多少のリファクタリング程度では、大抵の場合、焼け石に水です。どっしりと腰を落ち着けて、改善に取り組むことが必要です。その間、機能開発を止めることになるかもしれません。少なくとも、機能開発の時間の何割かは奪われます。そのようなビジネス判断は、とても難しいことです。

さて、この難題を突破して、リファクタリングやリアーキテクティングを進められたとしましょう。それで解決かと言えば、そう甘くはありません。それだけでは効果が一時的なものになります。3層目に手を打たなければ、いくらリファクタリングしても、次々とコードが複雑化していくからです。いたちごっこになってしまう恐れがあるということです。

なお、そもそもコードが複雑にならざるを得ないケースもあります。複雑なロジックを要する機能や仕様を実現しなければならないこともあるからです。このような複雑化については、本記事では取り扱いません。

3層目:組織設計のひずみ

既存コードの複雑化を誘発する3層目の正体はなんなのでしょうか。それこそ組織によって様々なのですが、組織設計が影響するというのが私の実感です。

これについては、2023年11月に登壇した技術カンファレンスにて、組織設計の失敗を8つのケースに分けて説明しました。すべてを詳細に説明すると長くなり過ぎるので、ここでは概要を述べるだけにとどめます。詳しくは、登壇資料をご覧ください。

  1. 共有リソースプール - プロジェクトの度にチームが刷新されるため、互いにうまくフォローしあえず、コード品質の悪化を防ぎきれない。

  2. 不連続なチーム - チームに連続性がなく、チームに蓄積された学びが失われるため、学びを活かした設計ができない。

  3. 非オーナーシップ制 - 領域ごとのコードの品質責任者がおらず、コード設計に一貫性が失われてしまう。

  4. 保守・運用の分離 - 分業によって、保守・運用の効率性が考慮されない開発が行われる。ドキュメントやコメントがないなど。

  5. 品質保証の一極集中 - 開発者が機能を実装することだけに専念し、テストコードを書かない。それが理解や変更の困難なコードを生む。

  6. 行き過ぎた固定化 - チーム編成に流動性がないために業務が属人化。コードも属人化し、他人からは理解しにくいものになってしまう。

  7. ドメイン知識の過疎地 - 企画と開発の分業が進みすぎたために、開発者にドメイン知識が蓄積されず、適切な設計ができない状態に陥る。

  8. 無力な他己管理型チーム - 開発者に決定権がなく、何をやるかがビジネス視点でのみ決定されるために、コードの複雑化に手を打てない状況が続く。

これらに対策を打てるのは、組織マネージャーや、プロダクト・プロジェクトの責任者です。どういう組織設計が正解であるか、それは不確実であり、また流動的でもあります。だから、組織設計も、リファクタリングやリアーキテクティングを繰り返しながら、より良い組織設計に近づけるための探索を続けることが必要になるでしょう。

ビジネス継続性に対する危険信号

1層目でも触れたように、「影響範囲の考慮漏れ」によるソフトウェアトラブルの多発は、ビジネスの継続性に対する危険信号です。このトラブルの原因をエンジニアの能力不足とみなしてしまうと、対策はおそらく1層目に対するもので止まってしまいます。それが意味するのは、ビジネスにおける競争力の喪失、つまりビジネスの死です。

問題の構造を分析し、より深い層まで手を打つことを忘れないようにしたいものです。


この記事が気に入ったらサポートをしてみませんか?