関数型プログラミングvsオブジェクト指向プログラミング[終了]


784

私はこれまで主にオブジェクト指向プログラミングに触れてきましたが、関数型言語を学ぶことを楽しみにしています。私の質問は:

  • オブジェクト指向よりも関数型プログラミングを選ぶのはいつですか?
  • 関数型プログラミングがより良い選択である典型的な問題定義は何ですか?



1
同様の質問cs.seも、関数型プログラミングが命令型スタイルよりも優れた結果をもたらす例を閉じまし。従来の知恵は、一方が他方より優れていない、または単純な基準で比較できない、またはさまざまな目的で使用されていると思われます...関数型プログラミングには科学的/学術的な起源と用途があり、業界ではあまり一般的ではありません、そのため、この質問は「産業界vs学界」の解決できないPOV /紛争も引き起こします。関数型プログラミングにおけるOOPスタイルを示す1つの古典的な参考文献、SICPブック/ MIT
vzn '27

OOは可動部分をカプセル化することでコードを理解できるようにします。FPは可動部分を最小化することでコードを理解できるようにします。
Micheal

回答:


1193

オブジェクト指向よりも関数型プログラミングを選ぶのはいつですか?

別の種類のソフトウェアの進化が予想される場合:

  • オブジェクト指向言語は、物事に一定の操作セットがあり、コードが進化するにつれて主に新しい物事を追加する場合に適しています。これは、既存のメソッドを実装する新しいクラスを追加することで実現でき、既存のクラスはそのままになります。

  • 関数型言語は、固定されたものがある場合に適し ています。コードが進化するにつれて、主に既存のものに新しい操作を追加します。これは、既存のデータ型で計算する新しい関数を追加することで実現でき、既存の関数はそのままになります。

進化が間違った方向に進むと、問題が発生します。

  • オブジェクト指向プログラムに新しい操作を追加するには、多くのクラス定義を編集して新しいメソッドを追加する必要がある場合があります。

  • 関数型プログラムに新しい種類のものを追加するには、多くの関数定義を編集して新しいケースを追加する必要がある場合があります。

この問題は長年にわたってよく知られています。1998年、フィルワドラーはそれを「表現の問題」と呼んだ。一部の研究者は、表現の問題はミックスインなどの言語機能で対処できると考えていますが、広く受け入れられている解決策はまだ主流に達していません。

関数型プログラミングがより良い選択である典型的な問題定義は何ですか?

関数型言語は、シンボリックデータをツリー形式で操作するのに優れています。好きな例はコンパイラーで、ソース言語と中間言語がめったに変更されない(ほとんど同じもの)が、コンパイラー作成者は常に新しい翻訳とコードの改善または最適化(物事の新しい操作)を追加しています。より一般的には、コンパイルと翻訳は、関数型言語の「キラーアプリ」です。


119
この答えの背後にはいくつかの深刻な禅があります。特定のOOP設計パターン(Visitor)が実際には新しい操作を追加する問題を克服しようとするハックであるという事実を明らかにしていると思います。
Jacobs Data Solutions

54
JavaScriptでは、すべてのものを持つことができます。
Erik Reppen 2013年

61
@ErikReppenこの時点で問題が発生します。いつ、関数型機能を使用することを選択し、いつオブジェクト指向機能を使用することを選択しますか?
ノーマンラムジー

7
@NormanRamsey JSで混同することは決して珍しくなく、ファーストクラスの関数はJS OOP関連の多くの機能に関連付けられています。JSの配列ソートは、強力なデータ構造を生成できる引数として関数を使用します。ほとんどのメソッドは単なる参照であるため、クロージャ+渡された関数を使用して、jqueryオブジェクトを非常に軽量なメモリスピーキングに維持します。その他...
Erik Reppen 2013年

9
@NormanRamsey:SICPに沿って非常に良い答え。この分類によれば、関数型プログラミングと手続き型プログラミングは、オブジェクト指向プログラミングの反対側でグループ化されます。これは、1980年代後半から1990年代初頭にかけてのOOPのブームを説明する可能性があります。GUIが主流になったとき、OOPは通常、固定の操作セット(ペイント、開く、閉じる、サイズ変更)を持っているため、それらをモデリングするための優れたアプローチであることが判明しましたウィジェットの数も増えています。もちろん、これは、あなたが説明したように、どのアプリケーションでもOOPが手続き型よりも優れているという意味ではありません。
Giorgio

177

必ずしも2つのパラダイムから選択する必要はありません。多くの機能概念を使用して、OOアーキテクチャでソフトウェアを作成できます。FPとOOPは本質的に直交しています

C#を例にとります。ほぼOOPと言えるかもしれませんが、FPの概念や構成は多数あります。Linqを検討する場合、Linqの存在を許可する最も重要な構成要素は本質的に機能的です:ラムダ式

別の例、F#。それは主にFPであると言うことができますが、多くのOOPの概念と構成が利用可能です。クラス、抽象クラス、インターフェースを定義し、継承を扱うことができます。コードをより明確にする場合、またはパフォーマンスを劇的に向上させる場合は、可変性を使用することもできます。

現代の言語の多くはマルチパラダイムです。

推奨読書

私は同じ船に乗っているので(OOPバックグラウンド、FPの学習)、私が本当に感謝しているいくつかの読みを提案します。


8
@duffymo:あなたのコメント、つまりあなたのコメントはほとんど無意味です。言語、仮想マシン、プラットフォームの比較を希望する人はいません。ありがとうございます。
Bruno Reis

6
@Bruno-「.NETのパワー」への応答。リラックス。
duffymo 2010年

6
おかしい、彼の無意味なコメントについてDykamをからかっているのを見かけない。私が見ていなかった間、あなたはモデレーターとして指名されましたか?あなたを除いて、誰もここで炎上することはありません。もう一度言います-リラックスしてください。
duffymo 2010年

4
なんか燃え始めたらすみません。他のプラットフォームはそれほど強力ではないと言ったわけではありません。.NETはOOPだけをサポートしていないということです。たとえば、末尾呼び出しの最適化があります。
Dykam、2010年

5
@ nawfal、2つのパラダイムのいくつかの固有の機能を指摘し、それらに互換性がないと言えるまで、それらは直交しています。それが議論の中心です。FPは本質的に命令型プログラミングと互換性がありませんが、OOPは命令型プログラミングに限定されません。これらの概念に異なる単語がある理由は、それらについて話すことができるようにするためです。それらをひとまとめにすると、不必要に新しい単語を思い付くだけです。
DavidS 2016

31

オブジェクト指向プログラミングは以下を提供します:

  1. カプセル化、
    • 内部状態の変異を制御する
    • 内部表現への結合を制限する
  2. サブタイピング、許可:
    • 互換性のある型の置換(多態性)
    • クラス間で実装を共有する大まかな手段(実装継承)

HaskellまたはScalaの関数型プログラミングでは、型クラスのより一般的なメカニズムを介した置換が可能です。変更可能な内部状態は推奨されないか、禁止されています。内部表現のカプセル化も実現できます。優れた比較については、HaskellとOOPを参照してください。

「関数型プログラムに新しい種類のものを追加するには、多くの関数定義を編集して新しいケースを追加する必要があるかもしれない」というノーマンの主張。関数型コードが型クラスをどれだけうまく使用しているかによって異なります。特定の抽象データ型でのパターンマッチングがコードベース全体に広がっている場合、実際にこの問題に苦しむことになりますが、それはおそらく最初から不十分な設計です。

EDITED型クラスについて議論する際の暗黙的な変換への参照を削除しました。Scalaでは、型クラスは変換ではなく暗黙のパラメーターでエンコードされますが、暗黙の変換は互換性のある型の置換を実現するもう1つの手段です。


3
型クラスは、他の型への暗黙的な変換のメカニズムではありません。それらは、ポリモーフィズムの形式を提供するために型に対して定義された関数のセットの記述です。JavaスタイルのOOPに最も近いのはインターフェースですが、Haskellの型クラスにはいくつかの重要な違いがあります。
Zak

25
  1. 非常に並行した環境にいる場合は、純粋な関数型プログラミングが役立ちます。変更可能な状態がないため、並行性はほとんど取るに足りません。Erlangを参照してください。

  2. マルチパラダイム言語では、変更可能な状態の存在が実装の詳細でなければならない場合に、FPが問題ドメインの優れたモデルである場合、いくつかの機能をモデル化することができます。たとえば、Pythonのリスト内包表記またはDプログラミング言語のstd.rangeを参照してください。これらは関数型プログラミングに触発されています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.