web-dev-qa-db-ja.com

OOP vs関数型プログラミングvs手続き型

これらのプログラミングパラダイムの違いは何ですか?また、特定の問題により適しているのでしょうか?

アーキテクチャの例に感謝します!

それらはすべて独自の方法で優れています-それらは同じ問題に対する異なるアプローチです。

純粋に手続き型のスタイルでは、データはそれを操作する機能から高度に分離される傾向があります。

オブジェクト指向スタイルでは、データは関数のコレクションを伴う傾向があります。

関数型では、データと関数は(LISPやSchemeのように)相互に共通性を高めつつ、関数が実際にどのように使用されるかという点で柔軟性を高めます。アルゴリズムは、ループと反復ではなく、再帰と合成の観点からも定義される傾向があります。

もちろん、言語自体はどのスタイルが優先されるかにのみ影響します。 Haskellのような純粋に機能的な言語でさえ、手続き型のスタイルで書くことができます(非常に推奨されませんが)。Cのような手続き型言語でさえ、オブジェクト指向のスタイル(GTK +やEFL API)。

明確にするために、各パラダイムの「利点」は、単にアルゴリズムとデータ構造のモデリングにあります。たとえば、アルゴリズムにリストとツリーが含まれる場合、機能的なアルゴリズムが最も賢明です。または、たとえば、データが高度に構造化されている場合、それがあなたの言語のネイティブなパラダイムである場合、オブジェクトとしてそれを構成する方が理にかなっているかもしれません-または、モナドの機能的な抽象化と同じくらい簡単に書くことができますHaskellやMLなどの言語のネイティブパラダイムです。

どちらを使用するかは、プロジェクトと言語がサポートする抽象化にとってより意味のあるものです。

120
greyfade

利用可能なライブラリ、ツール、例、およびコミュニティは、最近のパラダイムよりも完全に優れていると思います。たとえば、ML(または何でも)が究極の万能プログラミングかもしれません言語.

たとえば、ビデオゲームを作成している場合は、C++のより良いコード例とSDKがあります。小規模なWebアプリケーションには、Python、PHP、およびRubyの優れたフレームワークがあり、それらをすぐに実行できます。 Javaは、コンパイル時のチェックとエンタープライズライブラリおよびプラットフォームのため、大規模なプロジェクトに最適です。

以前は、さまざまな言語の標準ライブラリが非常に小さく、簡単に複製されていました-C、C++、アセンブラ、ML、LISPなど。基本が付属していましたが、物事の標準化に関してはニワトリが出がちでしたネットワーク通信、暗号化、グラフィックス、データファイル形式(XMLを含む)など、バランスの取れたツリーやハッシュテーブルなどの基本的なデータ構造も除外されました。

Python、PHP、Ruby、およびJavaのような最新の言語には、はるかにまともな標準ライブラリが付属し、多くの優れたサードパーティライブラリを簡単に使用できます。互いに衝突することや、ライブラリのメモリ管理スキームを標準化するガベージコレクション。

22
Dobes

これらのパラダイムは相互に排他的である必要はありません。 Pythonを見ると、関数とクラスをサポートしていますが、同時に、すべてが関数を含むオブジェクトです。 1つのコードで、機能/ oop /プロシージャスタイルをすべて組み合わせて一致させることができます。

私が意味するのは、関数型言語(少なくともHaskellで、私が研究した唯一の言語)にはステートメントがありません!関数内では1つの式のみが許可されます!!しかし、関数は一流の市民であり、他の多くの能力とともにパラメーターとして渡すことができます。数行のコードで強力なことができます。

Cのような手続き型言語では、関数を渡すことができる唯一の方法は関数ポインターを使用することであり、それだけでは多くの強力なタスクを有効にしません。

Pythonでは、関数は一流の市民ですが、任意の数のステートメントを含めることができます。したがって、手続き型コードを含む関数を作成できますが、関数型言語と同じように渡すことができます。

OOPについても同様です。 Javaのような言語では、クラスの外部でプロシージャ/関数を記述できません。関数を渡す唯一の方法は、その関数を実装するオブジェクトに関数をラップしてから、そのオブジェクトを渡すことです。

Pythonでは、この制限はありません。

20
hasen

GUIの場合、オブジェクト指向のパラダイムは非常に適していると思います。 Windowはオブジェクト、Textboxはオブジェクト、Okayボタンもオブジェクトです。一方、文字列処理のようなものは、はるかに少ないオーバーヘッドで実行できるため、単純な手続き型のパラダイムでより簡単になります。

それは言語の問題でもないと思います。ほぼすべての一般的な言語で、関数型、手続き型、またはオブジェクト指向を記述できますが、一部の言語では追加の作業が必要になる場合があります。

14
panschk

質問に答えるには、2つの要素が必要です。

  1. さまざまなアーキテクチャスタイル/パターンの特性の理解。
  2. さまざまなプログラミングパラダイムの特性の理解。

ソフトウェアアーキテクチャのスタイル/パターンのリストは、Wikipeidaの ソフトウェアアーキテクチャの記事 に示されています。また、ウェブ上で簡単に調査できます。

要するに、手続き型は手続きに従うモデルに適しています。OOPは設計に適し、機能は高レベルのプログラミングに適しています。

各パラダイムの歴史を読んでみて、なぜ人々がそれを作成したのかを見てみて、それらを簡単に理解できると思います。

両方を理解したら、アーキテクチャのスタイル/パターンの項目をプログラミングパラダイムにリンクできます。

6
GabrielC

それらはしばしば「対」ではないと思いますが、それらを組み合わせることができます。私はまた、あなたが言及する言葉はただの流行語であることが多いと思います。 「オブジェクト指向」が何を意味するのかを実際に知っている人はほとんどいません。たとえそれが最も激しい伝道者であってもです。

2
Svante

私の友人の一人が NVIDIA CUDA を使用してグラフィックアプリを書いています。アプリケーションはOOPパラダイムに非常にうまく適合し、問題はきれいにモジュールに分解できます。ただし、CUDAを使用するには、 継承 をサポートしないCを使用する必要があります。したがって、賢くする必要があります。

a)ある程度継承をエミュレートする巧妙なシステムを考案します。できます!

i) hook system を使用できます。これは、親Pのすべての子Cが関数Fに対して特定のオーバーライドを持つことを期待します。子にオーバーライドを登録させることができます。

ii)struct memory alignment 機能を使用して、子を親にキャストできます。

これはきちんとできますが、将来性のある信頼できるソリューションを見つけるのは簡単ではありません。システムの設計に多くの時間を費やすことになり、プロジェクトの途中で問題が発生しないという保証はありません。 多重継承 の実装は、ほとんど不可能ではないにしても、さらに困難です。

b)一貫した命名ポリシーを使用し、プログラムを作成するために divide and conquer アプローチを使用できます。継承はありませんが、関数は小さく、理解しやすく、一貫してフォーマットされているため、必要ありません。書く必要があるコードの量は増えますが、集中し続けるのは非常に難しく、簡単な解決策(ハック)に負けません。ただし、この忍者のコーディング方法は、Cのコーディング方法です。低レベルの自由と優れたコードの記述のバランスを保つこれを実現する良い方法は、関数型言語を使用してプロトタイプを作成することです。たとえば、 Haskell は、アルゴリズムのプロトタイピングに非常に適しています。

私はアプローチbに向かう傾向があります。アプローチaを使用して可能な解決策を作成しましたが、正直なところ、そのコードを使用すると非常に不自然に感じました。

1
sneg