世間一般的にOOP(オブジェクト指向プログラミング)が廃って久しいようですが、結局のところOOPを形づくる概念や手法のうち何が失敗だったのでしょうか?

マシン上での実現と静的なコード上での意味論を切り分けるという考えは革新的な気がしますし、データをオブジェクトの抽象状態と見なして状態と状態遷移に意味をもたせる方法は、イミュータブルなデータのやり取りをする方法には反しますが、一見合理的ですし、恐らく通常は効率的です。

問題解決の方法として、データとその操作をひとまとめにするのは自然な考えで、なるべくなら静的なコードとして扱いたい欲求から、型としてのクラスを定義することも悪くないと思います。この方向性では異なるデータを結び付ける操作を扱うにはぎこちなくなる気がしますが、これは大きな欠点になりますでしょうか?

ほとんどのプログラマは(他人の)ソースコードを読まないか(デコンパイルなどしない限り)読めないので(?)、多相性によって実行時の振る舞いが予測しづらいという指摘は(プログラマ個人としては理解できるものの)万人にとってそれほど重要でないのではないかと思います(逆にドキュメントを読んでコードを書くことは相対的によく行われている感があります。これは文芸的プログラミングと(多分に帝国主義的なこじつけをするなら)契約プログラミングの勝利でしょうか)。

継承によるコードの再利用性を得るという考えや、クラスをモジュールと見なしてクラス単位での再利用を狙うという考えは確かに全くの失敗で、再利用の実現方法としてはうまく行っていないでしょう。実装の継承は安全性の観点から全く不充分です。またコードの分割単位(場当たり的造語)としてクラスは大き過ぎ、クラスがメソッド(関数)を複数抱え込んでしまい意味を見失いがちという点はなんとなく納得できそうです。

実装の隠蔽による利益はあまり理解できない点ですが、これは現代でも奨励される作法でしょうか。例えばデータフィールドへのアクセサを定義し、そのインタフェースのみ公開することで状態の内部表現の変更に耐性を持つ(ついでに状態変更時に入力値を検証してクラスインスタンスの不変条件を保つ)ということがよく挙げられますが、自分の脚を打ち抜きたいプログラマはそう多くないという性善説(ないしチーム編成の勝利)を信じるならこれは全く余計なお世話だと思います。

最後に、OOPはスケールしない、という説をどこかで読んだ記憶があるのですが、これは事実でしょうか? 大規模開発に参加した経験がないのであまり理解できずにいます(往時の「大規模」開発にはOOPが強く勧められていたようですが……)。

色々書きましたが、OOPの欠点は、

  • 異なるクラスのインスタンス同士の相互作用を書きづらい

  • 多相性によって実行時の動作が予測しづらくなる

  • 実装の継承が危険

  • クラスが肥大化して再利用性や意味論を損ないがち

  • スケールしない(?)

といったところになるかと思います。これらの(またはこれら以外の)欠点としてどれが最も重視されているでしょうか?