IT業界で気づいたことをこっそり書くブログ

くすぶってるアプリエンジニアが、日々気づいたことを適当に綴っていきます(受託→ベンチャー→フリー→大企業→ベンチャー→起業)

技術的負債ならぬ、仕様的負債について

技術的負債っていう話、プログラマーは大好きです。
こいつらはコーディングの邪魔をし、プロジェクトを遅れさせ、残業を増やします。
だから皆嫌いなので技術的負債をどうにかしようと議論します。

技術的負債 - Wikipedia

 

ただし、概ね技術的負債を減らす術を身に着けてくると、それでもコードの複雑性が解消されないことに気づきます。
リーダブルに作っても、疎結合に作っても、SOLIDで作っても、どうしてもコードがぐちゃぐちゃになり、相当頭がいい人でないと全体を理解できない代物に成っていくでしょう。
あるいは新しく参画した、優秀なプログラマーたちによって作られたプロジェクトのコードが理解できずに悩むことで気づくかもしれません。

技術的負債の他に敵がいるということに。

 

その一つは仕様側の複雑性の問題です。
多くのプログラマーが気づくけど、中々手を出せず、それどころか議論にすら成りづらい仕様的負債について考えます。

 

f:id:otihateten3510:20210323081658p:plain

 

仕様的負債がどのように発生するか

このテーマだけで論文が書けそうなくらい重い話ですが。
今回は単純に「なぜ仕様が複雑化するか」の話を考えたいと思います。
私の観測範囲から見えてくる原因は、大体次のとおりです。

  • やろうとしてることがそもそも複雑
  • 市場最適のし過ぎ
  • 状態数を増やしすぎ
  • 施策の取り下げができていない
  • 環境の場合分け
  • 例外の作りすぎ

ちょっとずつ説明していきます。

 

やろうとしていることがそもそも複雑

Webサービスだと例えばECだとか決済だとか予約とかSNSだとか、あるいは国内向けのEMSだとかCSMだとかCMSだとか金融システムだとか、ああいうのはそもそもどう足掻いても複雑です。
複雑だからこそそれだけで仕事として成り立っています。導入に何億円もかかったり、それだけの機能を持った単一サービスが生まれたり。

これらは一回関わってみるとわかりますが、どれだけ単純化しようにも限界があります。ちなみに似たようなことが複雑性保存の法則で言われているらしいです。

 

市場最適のし過ぎ

例えば会社向けに導入するシステム開発などでよく言われますけど、会社側が自分達の仕事のフローの変更をせず、システム側にその複雑性を要求するとシステムがとんでもなく複雑になり工数が多くなります。

別の例で、最初にシンプルに作っていたサービスでも、売上が伸び悩んできて個々のユーザーに最適になるようにあれこれやってるとどんどん複雑になってきます。

 

状態数を増やしすぎ

例えばUserが1Modelとして存在していればいいんですが、UserをCustomer、Providerのように2Modelとして扱うと複雑度がかなり増します。
リボン型ビジネスとかそうですね。例えば売り手と買い手が居るようなシステムとか。
これに更に売り手、買い手、仲介のように3Modelにするともっと複雑度が増して工数が爆発します。

別の例で、Userを初回ユーザー、未ログインユーザー、ログイン済みユーザー、お得意様、のように分けていくとどんどん複雑になっていきます。

もっと小さいトランザクションレベルのところでも、送信前、送信中、送信後で3状態ですが、2つのトランザクションを組み合わせると3状態x3状態で最大9状態になります(ここは少し仕様的負債よりも技術的負債に近い気がしますが、2つのトランザクションを同時にやらなきゃいけない状況というのは仕様的負債だと思います)

こういう一見小さな状態数の増加で実はシステムの複雑度は爆発します。

 

施策の取り下げができていない

サービスをもっとよくしようとしてあれこれ入れたもので、あまり効果がなかったものが取り下げられていないケースです。これは謎の機能として邪魔をし続けますが、リファクタリングなどで解決できるものではありません。

以前見かけたのが、AppleGoogleに「新機能を入れたらアプリを目立たせてあげるよ」みたいな取引に応じた機能が放置されていたケースです。2,3社で見ました。

 

環境の場合分け

例えばiOSだと、iOSバージョン14,13,12,11,10,9で使えるみたいなアプリが有りましたがそこそこ地獄でした。
バージョンごとに書き方が異なるケースがあり、複雑度が上がっていました。
またはスマホだけじゃなくタブレットでも専用のレイアウトがあるだとか、小さい端末の時と大きい端末の時で処理を変えるとか、そういうケースがあります。

 

例外の作りすぎ

これは分かりやすいですよね。
実際のビジネスは例外のオンパレードです。ECサイトで「明日まで3000円以下の商品は送料無料」とか、状態数増やしてる上に例外を増やしています。
期限付きの例外とか注意しないと負債まっしぐらですよね。

 

仕様的負債が発生する理由(複雑度が上がる理由)

  • ビジネスがそもそも複雑
  • 構造が少し複雑になるとシステムは爆発的に複雑になるということに気づいていない
  • 人間の思考はプログラム的ではない
  • 工数が増えると嬉しい人達が居る
  • 非エンジニアの複雑度に対する危機感の薄さ

こんなところでしょうか?

 

仕様的負債が事業に及ぼす影響

  • どんな機能追加もひたすら遅くなる
  • バグが増える
  • バグかどうかの判断が付かない
  • 仕様を全部把握できる人が居なくなる
  • 優秀で高給な人しか改修できなくなる

どこでも起きてます。

 

仕様的負債を避ける方法

  • 複雑な仕様を安易に受け入れない(技術者サイド)
  • 単純な仕様を検討する
  • 使ってない仕様を破棄する

まあほとんどできてる所無いんですけどね。

 

エンジニアができる仕様的負債に対するアプローチ

現実問題これってあり得るんでしょうか。
仕様的負債の解消というのは技術的負債の解消よりも影響範囲も大きくどうなるか分からない部分もあります。イメージとしては盆栽の剪定作業のような感じですが、コア事業のために何かを捨てるとか変えるわけですから、そこへの責任が発生しますし、非エンジニア組織への説明やユーザーへの説明も発生します。

世の中どちらかと言えば、とにかく気にせず複雑にしてしまい、誰も触れないくらいになるんだけど、最終的に東大卒のエンジニアが長い時間をかけてちょっとずつ変更できるカタツムリのようなスピードで何とかやっていく、みたいな企業が多い印象です。それができないところは停滞していくという。

ライブラリーの開発など見ると、結構スクラップ・アンド・ビルドを繰り返しているので、ああいう風にできたらいいのにと思う一方で、ユーザーとしては「前と全然仕様が違う!」と苛つくこともあるのでどっちが良いんだろうと未だに答えが出ていません。

あと、すごくシンプルにした結果自分らの仕事がなくなるというケースも、いやそれはないか。やることは沢山ありますからね。

自分がこれからPOになることがあったらそこらへんの課題感を持ってやってみたいと思います。