内的品質を無視せざるを得ない状況に陥るな

ソフトウェアの品質

ソフトウェアの品質といえば, 大まかに外的品質と内的品質に分けられます.

  • 外的品質: ユーザーから見た品質
    • 例: 安全かつ確実に動作すること, 操作しやすいこと
  • 内的品質: 開発者から見た品質
    • 例: 変更しやすいこと, 型・linter・テストなどに守られていること, 読みやすいこと

当然ですが, ソフトウェア開発者としては外的・内的どちらの品質も高い, という状態を目指すべきでしょう. 場合によって優先度こそあれ, どちらかを一方的に切り捨てるべきではありません.

どちらの品質から高めるか

ある程度の複雑さを持ったソフトウェア (のコンポーネント) を作る場合, 大抵はどちらの品質も高い状態に向かって一直線に進めることはなくて, まずはどちらか一方の品質が高い状態を目指すのが普通かなと思います.

外的品質と内的品質の四象限図. 外的品質と内的品質の両方が低い現在地から, 両方が高い目的地に向かって, 先に外的品質と内的品質のいずれかを高める二つのルートがある

こういった開発の進め方については様々な流派があると思いますが, ここではどれが最適だという話はしません. どちらも状況によっては合理的な選択となり得ます.

リファクタリングの限界

ところでどちらの品質を先に高めるとしても, 片方の品質を高めた後に, もう片方の品質もその延長線上で高められるということが, 選択における暗黙の前提となっています.

実際にはこの前提は一般には成り立たちません. この世の複雑なものには一般に局所最適解というものが存在し得て, 例えば先に外的品質を十分に高めることはできたとしても, そこから内的品質を高める方向にリファクタリングすることは極めて難しいということがしばしば起こります. こうなってしまうと両方の品質が高い状態を目指すには, まずは局所最適解から脱出した上で, 改めて別の方向から目的地を目指す (言い換えると, 作り直す) ことになり, 二度手間になってしまいます.

外的品質と内的品質の四象限図. 外的品質のみが高い現在地から, 外的品質と内的品質の両方が高い目的地まで, 直線的なルートでは辿り着けず, 迂回したルートを通る必要がある

もちろん逆に内的品質を先に高めていたのに, そこから外的品質を高めることができないということも起こり得ます.

内的品質は無視されがち

外的品質と内的品質の大きな違いとして, 外的品質が低い状態は無視しづらいのに対して, 内的品質が低い状態は無視しようとすればできてしまうということがあります.

もし外的品質が低いと, そもそもソフトウェアをユーザーに提供することができなかったり, できたとしてもユーザーから全く使ってもらえなかったりします. こうした状況は致命的で, 無視できるとしたら開発自体を中止するときなどに限られるでしょう.

一方で内的品質が低かったとしても, 直ちにはそこまで致命的な状況になりません. 型エラーや linter のエラー, テストの失敗やそもそもそういった検査がないことなどは, ほとんどは技術的には無視することが可能です. もちろん長期的には設計などに負債が溜まって開発を中断せざるを得ないところまで行くかもしれませんが, 短期的には無視してもあまり大きな問題にはなりません.

それゆえ, 先に外的品質を高めたものの内的品質を高めることが難しかった場合には, ほぼ確実に内的品質は無視され, そのまま放置されてしまいます.

我々はどうすべきか

ここで考えるべきことは, 単純にどちらの品質を先に高めると良いかではなく, どちらの品質も高めるためにはどのようなルートで進むと良いかです. そもそも「先に外的品質を高めたものの内的品質を高めることが難しかった」といった状況が発生しないのが理想的なはずですよね.

一つはあらかじめリスクの高い箇所を考えて, その方向から進めるという作戦をとることです. 例えば外的品質を高められることは確実だが, そこから内的品質を高められるかが不確実であるといった場合は, 先に内的品質を高めることから始めます. 逆に後から外的品質を高められるかどうかが不確実なら, 先に外的品質を高めます. このように進めれば, もう片方の品質が高められないということが後になってから判明するリスクが下がり, どちらの品質も高い状態に辿り着く蓋然性が上がるはずです.

もう一つは小さく失敗するということです. とにかく先に片方の品質のみを高めて全体を完成させようとするのは, 局所最適解に陥るリスクを大幅に上げます. ソフトウェアを小さい単位に分割して, その細かい単位ごとに両方の品質を上げることを目指せば, 仮に一つ失敗したとしても全体を作り直すようなことにはならず, 総合的なリスクは小さくなります.

おまけ (一般論ではない話)

ところで私が遭遇するほとんどのケースでは, ソフトウェアに求められる要件は典型的で, 外的品質を高めることにそこまでの不確実性がありません (もし外的品質を高めることに不確実性があるような面白い話があったら呼んでほしい). また隣 (ネットワーク上) で開発しているメンバーを見ても, 外的品質を高める実装に苦戦している状況よりは, 設計や型, テストなど内的品質に関わる技術に苦戦している状況の方が多く見られるように思います. そのため, 少なくとも私の周りでは, 典型的には内的品質を先に高める方が品質が安定するだろうと考えています.