OOP vs関数型プログラミングvs手続き型[終了]


237

これらのプログラミングパラダイムの違いは何ですか?それらは特定の問題により適していますか、それともユースケースは他のものよりもどちらかを優先しますか?

アーキテクチャの例は高く評価されています!


これは完全な答えではありませんが、「機能的」が(OO#)スタイル(F#のコンテキストで)にどのように影響/コントラストを与えるかについて少し書きます:lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!511。エントリー
ブライアン

あなたはこれを読むことを検討するかもしれません使用する際の多くの例があります。これは何の蟻の主な違い、長所/短所など
ニキータIgnatov


1
次も参照してください: stackoverflow.com/questions/1530868
dreftymac

ボブおじさんがこれについてツイートしました。そして、ここにも。
jaco0646

回答:


129

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

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

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

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

もちろん、言語自体はどちらのスタイルが優先されるかにのみ影響します。Haskellのような純粋な関数型言語でも、手続き型スタイルで書くことができます(ただし、これはお勧めできません)。Cのような手続き型言語でも、オブジェクト指向スタイル(GTK +やEFL API)。

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

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


5
あなたが言ったことは、あなたが書いたものを反映していないようです。あなたは彼らに「長所と短所」がないと言い、次にそれらがどのように異なるアプローチであるかを言います。特定の状況に基づいて、なぜ誰かが別のアプローチを選択するのでしょうか?長所と短所、長所と短所、あなたがそれらを呼ぶものは何でも存在します!私はどちらかが本質的に優れていると言っているのではなく、あなたもそうではありませんでした。私はそれがあなたが本当に言いたかったことだと信じています。選択したアプローチには、別のアプローチに比べて良い点も悪い点もないと本当に信じていない限り。
JMベッカー

1
@TechZilla:私の言い回しが悪かったことに同意しますが、私が意味することは、言語XがアルゴリズムUと言語の記述により適していることを修飾せずに、言語XがYより優れていると言える機能のリストが実際にはないということですYはアルゴリズムVの記述に適しているかもしれませんが、どちらもどちらの言語でも簡単に実装できます。
greyfade '19年

2
手続き型と機能型の違いははっきりしません。私は大学でScheme / Rackettを学んでいますが、それと手続き型のCまたはPHPとの大きな違いは本当にわかりません。例を挙げていただけますか?
Leonel 2012

7
@Leonel:ほとんどの人が引用する最大の違いは、手続き型言語ではforループを使用する可能性があることですが、関数型言語ではそのようなことはありません。代わりに、関数の再帰呼び出しを使用して同じタスクを実行します。関数型言語は、関数をファーストクラスのオブジェクトにします。数値の場合と同じように渡すことができますが、Cでそれを行うことはできません(PHPによるサポートは壊れています)。
greyfade 2012

2
@tastro:あるパラダイムが他よりも理にかなっている場合。それだけです。関数の構成としてコードをモデル化する方が理にかなっている場合もあれば、データをオブジェクトとしてモデル化する方が理にかなっている場合もあります。アルゴリズムとデータ構造を表現する方法はたくさんあります。OOPと機能はたまたまそれらの2つです。
グレイフェード

25

利用可能なライブラリー、ツール、例、そしてコミュニティーは、今日のパラダイムを完全に打ち負かしています。たとえば、ML(または何でも)は究極の多目的プログラミング言語かもしれませんが、あなたがやっていることに適したライブラリを取得できない場合は、うんざりしています。

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

これまでは、さまざまな言語の標準ライブラリがかなり小さく、簡単に複製できました。C、C ++、アセンブラー、ML、LISPなどが基本に付属していましたが、標準化の際に問題が発生する傾向がありましたネットワーク通信、暗号化、グラフィックス、データファイル形式(XMLを含む)など、バランスの取れたツリーやハッシュテーブルなどの基本的なデータ構造も除外されました。

Python、PHP、Ruby、Javaなどの現代の言語には、はるかに適切な標準ライブラリが付属しており、ライブラリが互いに衝突しないようにするための名前空間の採用のおかげで、簡単に使用できる多くの優れたサードパーティライブラリがあります。ライブラリのメモリ管理スキームを標準化するガベージコレクション。


5
Python、ruby、...は単一の実装言語であるため、CやLISPなどの「標準」ライブラリはありません。PythonはGuidoによると、標準はありません。特定のCまたはLISP(またはその他)の実装には、現在、標準のライブラリを超える多数のライブラリが付属しています。
Dan Andreattaが

8
問題は、オブジェクト指向、関数型、手続き型プログラミングの違いについてでした。これらの回答で言及されている言語は確かにこれらのアプローチの1つに適していますが、回答はこれらの概念のいずれについても言及していません...「利用可能なライブラリ[...] [切り札]パラダイム」に関係なく、それは目の前の質問に答えないので、完全に有効な質問であるものを回避します。
rinogo 2013年


20

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

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

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

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

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

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


私はあなたが「これらのパラダイムは相互に排他的である必要はない」を意味したと信じています。それらの3つ直交しているので、理想的には、1つのプログラムで1つ、2つ、または3つを使用できます(言語で許可されている場合)。
ジョーピネダ

ええ、私は相互に排他的であることはそのためのより良い用語だと思います!おかげで
ヘイセン

14

GUIについては、オブジェクト指向のパラダイマが非常に適していると思います。ウィンドウはオブジェクトであり、テキストボックスはオブジェクトであり、OKボタンも1つです。一方、文字列処理のようなものはオーバーヘッドがはるかに少なくて済むため、単純な手続き型パラダイムでより簡単になります。

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


17
「オブジェクト= GUIウィジェット」という誤解を永続させるために反対票を投じたくなりますが、私は控えます。OOPは、「UserAccount」や「PendingSale」などの抽象的な概念を表すためにも、「ウィンドウ」や「ボタン」などの可視のインターフェース要素としても機能します。
Dave Sherohman、2009

5
ウィンドウをオブジェクトにできると書いた。すべてのオブジェクトがそこからのウィンドウであるという結論をどのように導きますか?ほんの一例です。もちろん、OOPは、抽象的なエンティティとそれらの関係をモデル化するためにも使用できます。とにかく、投票しないことに感謝します。とにかく私は多くのポイントを持っていません:D
panschk

6
-1。OOPはGUIとは何の関係もありません。理想的には、GUIを設計する最良の方法は、外部テキストファイル(HTMLなど)を使用することです。文字列処理のようなものは、実際にはオブジェクトを使用する方がはるかに優れています。(Cの文字列について考えてください)!!
Hasen

1
わからない、多分それを実現するためにオブジェクトを使ってプログラミングすることに慣れているだけかもしれません。しかし、TextBox Yの値がオブジェクトを使用せずに変更されたときに、TextBox Xの値を変更するなどのインタラクティブな操作をどのように実行しますか?さて、あなたは単にすべてにグローバル変数を使用することができます...
panschk

1
文字列処理はperl(Java、C ++またはC#の100倍)で素晴らしく行われますが、言語の文字列機能はオブジェクト指向ではありません。Cの文字列処理はひどいものでしたが、Cは唯一の手続き型言語ではありません(最良のものでもありません)。
ジョー・ピネダ

6

あなたの質問に答えるためには、2つの要素が必要です:

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

ソフトウェアアーキテクチャスタイル/パターンのリストは、Wikipeidaのソフトウェアアーキテクチャの記事に示されています。そして、あなたはそれらをウェブ上で簡単に研究することができます。

簡単に言えば、手続き型は手順に従うモデルに、OOPは設計に、関数型は高レベルのプログラミングに適しています。

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

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


2

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


1

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

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

i)フックシステムを使用できます。これは、親Pのすべての子Cが関数Fに対して特定のオーバーライドを持っていることを期待します。必要に応じて保存および呼び出されるオーバーライドを子に登録させることができます。

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

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

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

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


最初のc ++コンパイラーは、Cコードを生成するプリプロセッサーに過ぎませんでした。したがって、C ++のすべての機能(多重継承を含む)は、Cを使用して実装できます(CでのC ++例外処理のエミュレートには、例外に対する何らかのプラットフォームサポートが必要ですが、C ++実装にもそれが必要であるため、基本的なことだとは思いませんアイデアは無効です)。
Chris Becke、

2
@クリスベッケあなたの答えは哲学的すぎる。1つは、Cには複数の標準があり(年月を経て)、C ++はもちろんのこと、Cコンパイラによって完全に採用されたものはほとんどありません。C構文を使用しているため、C ++はCのスーパーセットであると言っても、1つのCコンパイラ用のコードを書くことさえできず、別のCコンパイラでコンパイルしても、大きな努力は必要ありません。さらに、Cを使用して新しい言語を設計しないとCに実装できない言語機能(型システム、OODサポート)があります(これがまさに「新しい言語」がある理由です)
Sprague

ええと。私のコメントがこの投稿にどのような関連があるのか​​、まったくわかりません。:P
Chris Becke

CudaはC ++をしばらくの間サポートしています。
Aryeh Leib Taurog、2015年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.