私の翻訳は、 元のレポートと同様に、コメントにさまざまな反応を引き起こしました。 そこで、ボブおじさんの回答記事を元の資料に翻訳することにしました。過去数年にわたって、多くのプログラマーは、OOPとFPは相互に排他的であると主張してきました。 雲の中の象牙の塔の高さから、FP天体は時々貧しい素朴なOOPプログラマーを見下ろし、慢なコメントに屈することがあります。 次に、OOPの支持者は、「機能」に頼りになり、左耳を右かかとで掻く理由を理解していません。
これらの観点は、OOPとFPパラダイムの本質を無視しています。 私は5セントを入れます。
OOPは内部状態に関するものではありません
オブジェクト(クラス)はデータ構造ではありません。 オブジェクトはデータ構造を使用できますが、実装の詳細は隠されています。 これがプライベートクラスメンバーがいる理由です。 外部からはメソッド(関数)のみが利用できるため、オブジェクトは状態ではなく動作に関するものです。
オブジェクトをデータ構造として使用することは、設計が不十分であることを示しています。 HibernateなどのツールはORMと呼ばれます。 これは間違っています。 ORMは、リレーショナルデータをオブジェクトにマップしません。 リレーショナルデータをデータ構造にマップします。 これらの構造はオブジェクトではありません。 オブジェクトはデータではなく動作をグループ化します。
ここで、ボブおじさんは、リッチなモデルではなく、貧血モデルに向かって頻繁にプッシュするものについてORMをscります。オブジェクト指向のような機能的なプログラムは、データ変換機能の構成です。 OOPでは、データと動作を組み合わせるのが慣例です。 それで何? それは本当に重要ですか?
f(o), of()
と
(fo)
間に大きな違いはありますか? 何、構文のすべての違い。 それでは、OOPとFPの本当の違いは何ですか? OOPにあるもの、FPにないもの、またはその逆
FIは割り当てに規律を課します(不変性)
Tru FPには代入演算子はありません。 「変数」という用語は、機能PLにはまったく適用されません。値を割り当てると、値を変更できないためです。
はい はい AFの謝罪者は、多くの場合、関数がファーストクラスのオブジェクトであることを示します。 Smalltalkでは、関数もファーストクラスのオブジェクトです。 Smaltalkは、関数型言語ではなくオブジェクト指向です。
主な違いはこれにありませんが、便利な代入演算子がありません。 これは、相転移に可変状態がないことを意味しますか? いや FP言語には、可変状態を操作できるあらゆる種類のトリックがあります。 ただし、これを行うには、特定の式を実行する必要があります。 状態の変化は複雑で、扱いにくく、AFにとって異質です。 これは例外的な手段であり、たまにしかためらわずにしか使われません。
OOPは、関数へのポインターを使用して作業に規律を課します
OOPは、関数ポインターの代わりとしてポリモーフィズムを提供します。 低レベルでは、ポリモーフィズムはポインターを使用して実装されます。 オブジェクト指向言語はあなたのために仕事をするだけです。 そして、これは素晴らしいです。関数ポインタを(Cのように)直接操作するのは不便だからです。チーム全体が複雑で不快な慣習を順守し、その都度従う必要があります。 通常、これは単に現実的ではありません。
Javaでは、すべての機能は仮想です。 つまり、Javaのすべての関数は直接呼び出されるのではなく、関数ポインターを使用して呼び出されます。
Cでポリモーフィズムを使用する場合、ポインターを手動で操作する必要があり、これは困難です。 Lispでポリモーフィズムが必要です。関数を自分で引数として渡す必要があります(ところで、これは戦略パターンと呼ばれます)。 しかし、オブジェクト指向言語では、これらはすべて箱から出してすぐに使用できます。
相互に排他的ですか?
2つの分野は相互に排他的ですか? PLは、割り当てと、関数へのポインターを操作するときに規律を課すことができます。 もちろんできます! これらはまったく関係ありません。 これらのパラダイムは相互に排他的ではありません。 これは、オブジェクト指向の機能プログラムを作成できることを意味します。
また、「関数ポインター」の規律を受け入れれば、OOPの原則とパターンを関数型プログラムでも使用できることを意味します。 しかし、なぜ「機能」のためですか? どんな新しい利点が彼らに与えられますか? そして、オブジェクト指向プログラムは不変性から何を得ることができますか。
多型の利点
多態性には1つの利点しかありませんが、それは重要です。 これは、ソースコードとランタイムの依存関係の逆です。
ほとんどのシステムでは、ある関数が別の関数を呼び出すと、ランタイム依存関係とソースコードレベルの依存関係は単方向になります。 呼び出しモジュールは、呼び出されたモジュールに依存します。 しかし、ポリモーフィズムの場合、呼び出しモジュールは実行時に呼び出されることに依存していますが、呼び出されるモジュールのソースコードは呼び出されるモジュールのソースコードに依存しません。 代わりに、両方のモジュールはポリモーフィックインターフェイスに依存しています。
この反転により、呼び出されたモジュールはプラグインのように動作できます。 実際、プラグインはそのように機能します。 プラグインアーキテクチャは非常に信頼性が高く、安定した重要なビジネスルールを変更の対象とは別に保存でき、それほど重要なルールではありません。
したがって、信頼性のために、システムは意味のあるアーキテクチャの境界を作成するためにポリモーフィズムを使用する必要があります。
不変性の利点
不変データの利点は明らかです-何も更新しない場合、同時更新の問題に遭遇することはありません。
ほとんどの機能PLは便利な代入演算子を提供しないため、このようなプログラムでは内部状態に大きな変化はありません。 突然変異は特定の状況のために予約されています。 直接的な状態変更を含むセクションは、マルチスレッドアクセスから分離できます。
全体的に、機能プログラムはマルチスレッドおよびマルチプロセッサ環境ではるかに安全です。
退屈な哲学
もちろん、OOPとFPの支持者は私の還元主義者の分析に反対するでしょう。 彼らは自分の好きなスタイルが他のスタイルよりも優れている重要な哲学的、哲学的、数学的な理由があると主張します。 私の反応は:Pffff! 誰もが自分のアプローチが優れていると考えています。 そして誰もが間違っています。
では、原則とパターンはどうでしょうか?
何が私をそんなに困らせたのですか? 最初のスライドは、何十年にもわたって開発してきたすべての原則とパターンがOOPにのみ適用可能であることを示唆しています。 そしてFPでは、すべては単に関数によって決定されます。
うわー、その後、あなたは還元主義について何か言いますか? アイデアはシンプルです。 プログラミングスタイルに関係なく、原則は変わりません。 便利な代入演算子なしでPLを選択したという事実は、SRPまたはOCPを無視できるということではなく、これらの原則が何らかの形で自動的に機能することを意味します。 「戦略」パターンがポリモーフィズムを使用する場合、これは機能PL(Clojureなど)に適用できないという意味ではありません。
全体として、調理方法を知っていればOOPは機能します。 FPについても同様です。 機能的なオブジェクト指向プログラムは、それが何を意味するのかを本当に理解していれば、一般的に素晴らしいです。