Re: オブジェクト指向はすでに粒度が時代にあっていない

この記事はオブジェクト指向はすでに粒度が時代にあっていない - きしだのHatenaの個人的補足である……本当は書くつもりはなかったのだけど、ちょっと気になったので。

あの記事の趣旨なのだが、乱暴に言うと:

OOA + OOD + OOP」の勝利の方程式でV10達成必至――そんなふうに考えていた時期が俺にもありました

――といった感じだと考えている。ちなみに上記の「俺」は特定の誰かを示している訳ではないので注意すること。特に、「俺」は id:nowokay を指していない。というか元記事のニュアンスは「最近の大規模な『業務システム』や『Webサービス』を『1から丸ごと構築する』という粒度のシステム開発では、その構図は成立しないよね」といった感じのことを言っているだけなので*1

オブジェクト指向」という言葉を使用しているためか、元記事について妙な反応が多い気がするのだが、一応、この辺は元記事に:

とりあえずオブジェクト指向の話をすると定義が人によって違いすぎるので、改めてここでの定義を書いておくと、基本的にはOMTの「データ構造と振る舞いが一体となったオブジェクトの集まりとしてソフトウェアを組織化すること」に従うのですが

――と書いてあって、要は「『システム≒オブジェクトの集合』という前提に基づいて『要件モデリング → 分析モデリング → 設計モデリング → プログラミング』と開発を進めていく」みたいな流れを想定しているのだと思う。

で、ここから半分雑談。

元記事について「結局は『OOA + OOD + OOP』は銀の弾丸ではなかっただけ。他のソフトウェア開発手法と同様に、状況次第で薬にも毒にもなる」と感想を述べるのは容易いのだけど、では薬と毒の境界はどの辺にあるのだろうか?

個人的に、目安の1つとして「そのシステムが『1つのコンピュータ上の1つのプロセス』ぐらいの粒度におさまるか?」という視点があるのではないか、とぼんやり考えている*2

開発するソフトウェアの性質に依存する話ではあるのだけど、例えば単一の「アプリケーション/デーモン/ちょっとリッチな組み込み機器のファームウェア」を開発するケースでは、開発するソフトウェアの中身を「オブジェクトの集合」として組織化する前提で「OOA + OOD + OOP」で開発するのは悪くない考えであるし、2021年の時点でもそれなりに通用すると思っている。もちろん、それが「常にベストな方法」だとは思っていないのだけど*3

ところでモダンな大規模システムは、システム全体を見渡すと「複数のマイクロサービスと複数のクライアント・アプリケーション」で構成されていたりするのだけど、これは「システム≒オブジェクトの集合」という発想との相性が悪いと思う。

なぜなら、プログラマの視点から見た時、例えば個々のマイクロサービスは「オブジェクト」として抽象化されていないから。だから「システム≒オブジェクトの集合」として組織化したいならば、個々のマイクロサービスを「オブジェクト」として抽象化して、他の有象無象のオブジェクトと同様に扱えるように作りこむ必要がある。だけどそれは一大事業になってしまうから、例えば「内部でHTTPS通信してWeb APIを叩く」みたいなお手軽class実装でお茶を濁してしまう。

その「お手軽class実装」をもって「マイクロサービスを『オブジェクト』として抽象化した」と言えるのか……? 多分、言えない。その「お手軽class実装」は「マイクロサービスAとの通信モジュールのオブジェクト指向プログラミングによる実装」でしかない。

これは、例えるなら「UnixPlan 9でのネットワーク・プログラミングの違い」の拡大解釈版みたいな話だ。Plan 9は「everything is a file」が徹底されているので、TCPクライアント/サーバは「ファイルのopen/read/write/close」として実装する。でもUnixではそこまで抽象化されていない。では、Unix上で動くTCPクライアント/サーバを実装する時に「Plan 9と同程度の『ファイルによる抽象化』の階層(※ただしTCP/IPネットワーク限定)」を構築してからクライアント/サーバを実装するか?」と問われれば、そんなことはなくてBSD Socketプログラミングしちゃうよね……という話だ。

TCP/IPネットワークが「ファイル」として抽象化されているのならば、「ファイル操作」という視点で「分析 → 設計 → プログラミング」することは適切だろう。でも、「ファイル」として抽象化されていないならば、「ファイル操作」という視点に基づいて開発するのは間違っているはずだ。

最近の大規模システムでは、もはやシステム全体について「システム≒オブジェクトの集合」と考えることは適切ではないので、「システム≒オブジェクトの集合」を前提とした「OOA + OOD + OOP」を「システム全体」に適用するのはミスマッチだという話になる。

(元記事とは違ってボトムアップな議論ではあるけど、元記事にもある「粒度があっていない」とは、こういった側面も指し示している気がする)

もちろん「システム全体」ではなくて「個々のサブシステム」――それはマイクロサービスの中身だったり、クライアントアプリだったり、何らかのソフトウェア・コンポーネントだったりするのだろうけど、「サブシステム」ぐらいの粒度においては「サブシステム≒オブジェクトの集合」と見なして「OOA + OOD + OOP」する余地があるだろう*4

そして、小規模システムならば、つくるモノ次第ではあるけど、今でも「システム全体」について「システム≒オブジェクトの集合」として「OOA + OOD + OOP」するアプローチがそれなりに通用する。

……うーん、アレか、うまく言えないけど「ネットワークを介した分散システム」か否か、みたいな点がキーなのだろうか? この辺の諸々って、実用的で汎用的なライブラリ/フレームワークで「大きな粒度」での「オブジェクトとして抽象化」がなされてないと思う。その上で、「全てをオブジェクトと見なせる抽象化層」を作りこむのは非常に大変だろう。だから「システム全体」を分析・設計する時には「そんな抽象化層は存在しない」という前提で話を進めることになる

(この辺が元記事にて「マイクロサービス」や「Web API」といった単語が出てくる遠因となっている気がする。「マイクロサービス」そのものは「オブジェクトとして抽象化」せず、マイクロサービスのまま扱って「Web API」を叩く――という前提でサーバサイドをサービス単位に切り分けてWeb APIを設計する、みたいな感じ? うまく表現できないのだけど……)

一方で、前述でいう「個々のサブシステム」みたいな粒度だと、出来合いのライブラリ/フレームワークによる抽象化がちょうど良い感じであったり、自前で抽象化層を造りこむコストがそこそこ低いことが多いから、「じゃあ『サブシステム≒オブジェクトの集合』として組織化する前提で、分析・設計・プログラミングしましょうか」という話がコスト面で許される余地がある、という感じだろうか。

蛇足:ところで「元記事は『最近の大規模システム』の粒度を念頭に語っている」というのは半分以上私の推測なのだが、元記事の最後の方に「オブジェクト指向開発のコンサル」への言及があるので、おそらく暗黙の了解として「コンサルを入れるだけの資金を確保できる大規模エンタープライズ開発」あたりを想定しているのだと思う。Enterprise JavaBeansといった単語も出てくるぐらいだから、的外れではないと思っている。

*1:――と私は読み取っている。

*2:あくまでも「目安の1つ」でしかない点に留意すること。

*3:つくるモノに依存する話なので。

*4:そして、もちろんそれが「常にベストな方法」という訳ではないのだろうけど。