オブジェクト階層の沼

2021/01/18

ソフトウェア開発のうち、妙手がなく、とにかく生産性が落ちる分野の1つが、階層の深いオブジェクトの操作だ。
データの集合は、主に配列と連想配列(Rubyではハッシュ、Javascriptではオブジェクト)がある。配列は同じデータが並んでいるもので、連想配列はIDなどのキーに対応するデータを持つ構造になっている。

配列は、キーが0, 1, 2, 3,…である連想配列とも言えるのだが、どの言語でも配列を操作する関数と連想配列を操作する関数とは同じではない。
概念的に同じようなものだと思っていても、書くべきコードはパートにより多種多様だ。

階層の深いオブジェクトというのは、マトリョーシカのように配列の中に連想配列があるような複合構造のデータで、その構造に制約がないためすぐに複雑化する。

単に構成要素が多いということだけでなく、以下のような難点がつきまとう。

  • 配列と連想配列が混じることによる複雑さ
  • 任意の部分が空集合になりうる。不用意にアクセスすると異常動作
  • 目的に応じて変形しなくてはならない

たとえば、データ構造の5%を変更するコストはトータルの5%であって欲しいが、取り扱い方が変わればどれほど時間がかかるのか今ひとつ見通しが立たなくなる。
大規模システムほど設計が問われるのは、将来の変更を予知して採り入れてしまい、構造変更を起きにくくするためだと言って良いだろう。

相互に埋没する問題

少し違った角度から生産性のネックを観察すると、複雑なオブジェクトほどコード量が増えるという素朴な編集技術上の難点も大きい。

オブジェクト指向や関数プログラミングといったいくつかの設計パラダイムがあるが、どのようなパラダイムを採用しても結局のところソースファイルには行と列の2次元しかない。
いずれの手法でも主のパラダイム以外の面は凝集性を失うため、次元が増えるほどにフリーランチの余地はなくなる。

たとえば、認証やログなどのセキュリティ機能は cross-cutting concern として知られているが、これはどのパーツにも必要になる機能がコードの全体に散らばっている様子を捉えている。
一般化すれば、副次的な機能がソースコードの紙面の範囲に収まらない問題と言える。

パラダイムの裏側に隠れてしまった次元の保証は、現状、洞察力でカバーせざるを得ない。エンジニアの追加で問題解決できないことは人月の神話として知られている。

スタティックなファイルを超えるしかない

ネストの問題は、プログラムコードの扱う次元が多いことに比べてファイルが2次元しかないというギャップから生まれている。
この問題の解決は、射影技術の向上、すなわちソースコードの編集過程でインタラクティブに変換することだと思う。

たとえばオブジェクト指向と関数プログラミングは別のバラダイムではなく、2つのビューとして相互に変換可能になるべきだろう。

このような等価変換が可能になるためには、数学的に証明された体系が必要になる。
プログラムコードは無矛盾であることを求めているから、各次元に着目して記号体系を射影する構造はとくに問題なく存在するのではないか。

おそらく同様の発想はすでにあるのだと思う。ただ、商業ソフトウェアになりづらいネックも理解できる。
現在のプログラムは概ね100%人手で書いたファイルであり、バグがあれば書き手の責任であることは明確だ。これをツールが積極的に変換するとなれば、問題の所在は分かりにくくなる。

水かけ論で訴訟が頻発するようなツールは作りたくないだろう。

一方で、健全な結論は自明であり、どのような変換を施そうともコードの書き手の責任であることは変わるべきではない。
円滑な導入のためには、学術的な裏付けのもとにオープンソース実装を普及していく形態がスムーズだろう。

コードの凝集性に進歩がなければ、大局的にみてソフトウェアの生産性は一切改善しない。
物理学の進展を考えれば、情報工学もそれくらいの進歩はできそうなものだと思う。

⁋ 2021/01/18↻ 2021/01/25