acomagu's diary

思ったことを書きます。技術的なことは書きません。

オブジェクト指向は難しくない(「staticおじさんの逆襲」への反論)

qiita.com

これを読んでいろいろと言いたいことが出てきたので書いておく。

以下に記事の最後のこの記事で言いたかったことから2つを引用します。

オブジェクト指向は難しい。

(どのあたりのことを「難しい」と言っているのだろう)まず「継承は難しい」旨が書いてあるが、それはオブジェクト指向使いの中でも常識で別に継承無しでもオブジェクト指向はできる。「継承よりもコンポジション」というのは間違っても「オブジェクト指向はダメだ」というメッセージではなく、オブジェクト指向の中での方法の話である。

デザインパターンが難しい」という話も同じで、別にデザインパターンを意識しなくてもオブジェクト指向は十分にできる*1

ただ、だからといってオブジェクト指向をやるのが難しくないというわけでもない。「問題を(オブジェクトに)抽象化するのが難しい」と言っているのであればそれはそうで、適切な抽象化を簡単にする方法はまだ誰も見つけていないように思えるし、適切な抽象化が無いことにはオブジェクト指向のメリットは得られない。ただし、「適切な抽象」を考えることは本質的には課題を理解し分割して名前をつけるようなものなので、関数型プログラミングならそれなしにできるかというと疑問だ。

例えば「円からドルへの変換」するプログラムを関数型パラダイムを使用して書くことを考えてみたいと思う。これは単純で、円の値にドルへの為替レートを掛ければ良いと思う。じゃあそこで「ドルから円」「円からユーロ」の変換する必要も出てきたらどうだろうか。「円」や「ユーロ」は「通貨」へ、「円からドルへの変換」は「通貨から通貨への変換」へと抽象化したくなるのではないだろうか。すべての抽象化はその延長上にある。オブジェクト指向でもほぼ同じで、それらの違いはデータ(「通貨」)と操作(「変換」)を近くに置いてより豊かな抽象的表現を追求するか、あるいはそうではなく純粋関数から得られるメリットを重視するか程度だと思う。

よってオブジェクト指向が特に難しいわけではなく「オブジェクト指向では抽象化がより重視されている(そして抽象化は難しい)」程度の認識が正しいのかなと思う。抽象化なしにはプログラムの可読性も柔軟性も(正しい変数名さえも)得られないので、その点で関数型プログラミングのほうが優れているということは無いと思う。

複雑さはそれ自体害悪である。単純なのはよいことだ。

「単純」がどのベクトルを指して言っているのかいまいちわからないけれど、例えばそれが「コード量」の話であるなら最も単純なのはオブジェクト指向でも関数型でもなく、命令型プログラミングになると思う。

オブジェクト指向でも「抽象化しすぎ」という状態はある。例に上がっている「FizzBuzzEnterprizeEdition」は明らかにその状態だと思う。可読性や柔軟性が十分であるのにそれ以上のカプセル化ポリモーフィズムを多用することが無意味な複雑化につながることは想像に難くない。

元記事に書いてあるとおり、僕達は「複雑な課題を簡単に解決する」ために抽象化に頭をひねらせる。課題が十分に複雑でないなら、抽象化なんて要らない。

まとめ

  • オブジェクト指向は難しくない。難しいのは抽象化である。
  • 継承もデザパタオブジェクト指向プログラミングをする上で必須なものではない
  • 抽象化こそがプログラムの可読性と柔軟性を作り出す(これは元記事にも書いてある)
  • どちらにせよ抽象化し過ぎは悪。

思ったこと

自分も数年前までは「これからは関数型の時代だ!」と思ってオブジェクト指向を禄にやっていなかったのだが、いろいろあってちゃんと勉強したら「長く支持されているものにはちゃんとした理由があるのだなあ」と実感した勢なので、「オブジェクト指向よく知らないけれどオワコンなんじゃないの?」と思っている人たちは一度どっぷり浸かってみてほしいと思う。

おわり

*1:そもそもデザインパターンは言ってしまえば「パターン」でしかないのでオブジェクト指向の本質でもなんでもない。(個人的には)使えるときに使ったらいいという感覚

Add Star
  • id:yusuke-furuya-tech

    Qiitaでコメントをしてた@yuu341です。
    私の所感を述べますとやはりオブジェクト指向は難しいと思います。
    プロジェクト単位で考えると使い方をわかっていないがために足を引っ張る人はたくさんいます。初学者でも熟練者(自称)でもです。
    そういった人たちがたくさん蔓延っているんですから、つまりは全体での学習難易度は高いのではないでしょうか。

    >「継承は難しい」旨が書いてあるが、それはオブジェクト指向使いの中でも常識
    それはオブジェクト指向使いの中でもということであって、まだそうではない初学者にとっては有用性やデメリットが把握できずにいると思います。
    よって教本通り「基底クラスのメンバにアクセスできる!再利用!」みたいなのに釣られて継承の継承の継承みたいなものを作ったりするんだと思います。

    もちろん継承に限った話ではないです。HogehogeUtilityみたいな神クラス、SOLID原則の無視。
    これらを回避するには何故うまくいかなかったのか、どうすればよかったのかを常に検討し続ける必要があり、それらを含めると習得への道のりは遠いと言わざるを得ないかと思います。

    >「デザインパターンが難しい」という話も同じで、別にデザインパターンを意識しなくてもオブジェクト指向は十分にできる。
    オブジェクト指向というのは@acomaguさんにとってどういう技術群のことを指すのでしょうか?
    デザインパターンを検討して開発をしなければOOPのパフォーマンスは発揮されないと思いますし、検討せずとも作ったプロジェクトは破綻せずに回るのでしょうか。
    あるとすればそれは要件が単純だとか、大規模ではないプロジェクトなのではないですか?

    ソフトウェア資産は生物であり、大体は作って終わりではなくそのあとの追加開発や保守も含めて考えるものです。
    その時に流動的要素、問題領域を検討しなかったプロジェクトは修正コストに多大な技術的負債がのっかるか、それを無視してさらに保守性の悪いコード群を量産し続けるかです。
    そういうものをひっくるめて保守性の高いコードをクラス間構造でアダプティブに表すのがOOPだと思いますし、その習得は失敗と学習の連続です(こういっちゃなんですが私自身もどこまでやればオブジェクト指向を習得したといえるのか不明ですし)。