オブジェクト指向プログラミングは複雑さの解決策だと思いますか?どうして?このトピックは少し物議をかもすかもしれませんが、ここの専門家からなぜの答えを知るつもりです!
オブジェクト指向プログラミングは複雑さの解決策だと思いますか?どうして?このトピックは少し物議をかもすかもしれませんが、ここの専門家からなぜの答えを知るつもりです!
回答:
複雑さに対する解決策はありません。
「The Mythical Man-Month」では、Fred Brooksが、プログラミングにおける偶発的な複雑さと本質的な複雑さとの違いについて説明しています。偶発的な複雑さは、アイデアを直接表現できないため、言語で追加のコードを記述してテストする必要があるなど、ツールや方法が原因です。新しい方法と手法により、偶発的な複雑さが軽減されます。より良い言語とツールを持っているので、私は25年前よりも速く、より良いプログラムを書くことができます。
本質的な複雑さは、プログラミングでやろうとしていることが本質的に複雑であり、削減できない複雑さがあるという事実から生じます。この文脈での「必須」とは、「非常に必要」ではなく、「物の本質に関する」ことを意味します。
したがって、彼は特効薬はなく、ソフトウェアの作成は引き続き困難になると主張した。
彼の本を読むことを強くお勧めします。具体的には、Silver Anniversaryエディションに追加のエッセイ「No Silver Bullet」をお勧めします。その中で、彼は複雑さに対して提案されたソリューションをレビューし、その影響を検討します。(彼が最も効果的だと思うのは、シュリンクラップソフトウェアです。複雑なものを一度書いて、数千または数百万のコピーを販売します。)
現在、オブジェクト指向プログラミングは、適切に行われたときに、抽象化を作成し、複雑さを隠すことにより役立ちます。クラスのオブジェクトには、実装の複雑さを気にせずに推論できる特定の動作が定義されています。適切に記述されたクラスは、相互の結合度が低く、分割統治は、複雑さを回避できれば複雑さに対処するための優れた方法です。また、これらは互いに密接に関連する一連の関数とデータであるという点で、高い凝集度を持っています。
すぐにもっと良い答えが得られると期待していますが、簡単なものを次に示します。
OOPは、世界の他のすべてのものをモデル化する方法により近い方法でソフトウェアをモデル化することにより、複雑さを支援します*。一連のルーチンやデータ構造を考えて同じことを行うよりも、壁オブジェクトと相互作用するボールオブジェクトをイメージする方が一般的に簡単です。現実世界と相互作用する方法に近いためです。
*複雑さを「解決」することはできないため
OOPの現在の主流の定義は、複雑さを管理するための良いソリューションではないと思います。
ルーツに戻ると、アラン・ケイは「lisp」に多大な影響を受けていたと思います。
Lispは主流の採用によって破壊されていないため、おそらくそのコアバリューを保存することができたでしょう。したがって、この複雑さの問題にLispがどのように取り組むかを見ると、ある程度の洞察が得られると思います。複雑さを扱う上でOOPがどれほど役立つかを判断するための基礎としてそれを使用できます。
SICPの「レクチャー3a:ヘンダーソンエッシャーの例」の終わりを見ると、Hal Abelsonは、タスクを小さなサブタスクに分割するのではなく、抽象化の層を作成することによって複雑さを管理することを提案しています。最高レベルでは、複雑な問題の解決策を、下位レベルの抽象化の解決策の観点から表現します。
OOPは元々、これらの抽象化層を作成するメカニズムとして意図されたと思います。
残念ながら、今日では、OOPはスパゲッティコード/構造を記述するために(ab)使用されています。
私は例を作ります:FPSマルチプレイヤーゲーム。
最高レベルでは、ゲームは多くのプレイヤーがマップを走り回り、武器を使用してお互いに射撃することで機能します。
次のレベルでは、マップと武器とプレイヤーについて話さなければなりません。おそらく、ゲームの世界内で相互作用する物理オブジェクトとしてそれらについて話すことができます。
次の下位レベルでは、オブジェクトが物理的にどのように相互作用するか(動き、衝突など)について話すことができます。
などなど。
これが意味することは(そして、私はSICPから引用しています)、各層で、特定の特定の問題を解決するだけでなく、問題の近隣にある種の問題を解決するということです。解決しようとしています。そのため、問題の説明にわずかな変更がある場合でも、ソリューションにわずかな変更を加えるだけで済みます。
したがって、OOPを使用する賢明な方法は、抽象化の各レベルで抽象化のレイヤーを作成し、そのすぐ下のレベルの「オブジェクト」を使用して手元の問題を解決することです。
講義から引用した部分は次のとおりです。http://www.youtube.com/watch?v = CYtrfncMqHQ
いつものように、私は皆に同意しません。複雑さを管理するためのツールを提供するどころか、OOPは不十分で数学的に偽のパラダイムであるため、膨大な量の複雑さを生み出します。OOPでモデル化できないオブジェクトをOOPでモデル化しようとすると、プログラマーは終わりがありません。
私の見解では、ここでの重要な仕事はMeyerのオブジェクト指向ソフトウェア構築です。それは、私が重要だと思うものを含む、一連の要件を詳述しています:オープンクローズドプリンシパル。これは、あるものは拡張のために開かれているが、使用のために閉じられている必要があることを同時に示しています。
Meyerは、エッフェルで具体化されているように、これらの要件からオブジェクト指向を導き出します。カプセル化は、クロージャ、継承のオープン性を提供し、言及されている「もの」はクラスです。
Meyerは明らかに間違っていたので、この研究は優れた科学であると考えています。また、彼の研究の質のために、エラーを特定して修正することは可能です。
エラーは、クラスまたはタイプをモジュール化の単位にしています。それは間違っています、そして確かにそうです。Meyerでさえ、OOPは1より大きいアリティの関係を処理できないという問題(共分散問題と呼ばれます)を認識しました(つまり、OOPはプロパティに対しては正常に機能しますが、バイナリ関係では失敗します)。エッフェルでは、この問題により型システムが不健全になりました!
解決策は非常に明確です。モジュール性の単位は、単一のタイプよりも大きくなければなりません。それはいくつかのタイプ、およびそれらに関連するメソッドで構成されなければなりません。
この抽象化のモデルが抽象化の数学的理論、すなわちカテゴリー理論に裏付けられていることは驚くにはあたりません。タイプはカテゴリーのオブジェクトであり、メソッド(関数)は矢印です。
このモデルでは、いくつかのタイプの表現が一連の関数に認識されます。表現は公開されていないため、これはカプセル化ですが、クラスではなくモジュールを使用します。
Standard Meta-Language(SML)とOcamlは、このモデルに直接基づいています。OcamlにはクラスとOOPもあります。OOPを使用するとプロパティ(動的バインディング)のディスパッチが可能になるため、役に立たないわけではありません。しかし、実際の問題のほとんどはリレーションシップに関係しており、Ocamlでクラスがあまり使用されていないことは驚くに値しません。
C ++標準テンプレートライブラリで継承が使用されることはほとんどありません。
簡単な事実は、OOPは複雑さを処理するための適切なツールを提供せず、本当に単純な問題を処理するためのツールも提供せず、代わりに2世代のプログラマを誤解させ、混乱させていることです。助けとはほど遠い、OOPはC、Fortran、Cobolが疲れ始めてからプログラミングに起こった最も悪で悪いことです。
オブジェクト指向プログラミングには、1960年代までさかのぼることができるルーツがあります。ハードウェアとソフトウェアがますます複雑になるにつれて、管理性がしばしば懸念事項になりました。研究者は、ソフトウェアの品質を維持する方法を研究し、プログラミングロジックの個別の再利用可能なユニットを強調することにより、一般的な問題に対処するためにオブジェクト指向プログラミングを開発しました。
したがって、オブジェクト指向プログラムは、プログラムが実行するタスク(サブルーチン)のリストとして見られる従来のモデルとは対照的に、相互作用するオブジェクトのコレクションとして見ることができます。OOPでは、各オブジェクトはメッセージを受信し、データを処理し、他のオブジェクトにメッセージを送信できます。各オブジェクトは、別個の役割または責任を持つ独立した「マシン」と見なすことができます。これらのオブジェクトに対するアクション(または「メソッド」)は、オブジェクト自体と密接に関連しています。
http://en.wikipedia.org/wiki/Object-oriented_programming
この懸念の分離は、ポリモーフィズム、継承、メッセージパッシング、デカップリング、カプセル化などのオブジェクト指向の他の機能とともに、大規模プログラムの複雑さを非常に効果的に管理できる論理的および概念的なフレームワークを提供します。
ソフトウェア開発には多くの種類の複雑さがあります。プログラミングレベルでは、OOPはオブジェクトとクラスを使用して問題領域をモデル化することにより、複雑性に対処しようとします。有名な第一人者は、問題解決は単に問題を表現しているので、解決策は表現そのものであると言いました。したがって、クラスを使用した抽象化、アクセス修飾子とメソッドを使用したカプセル化、関係と再利用を指定するための継承、クラス間の関係とコラボレーションの確立における構成、類似オブジェクトのさまざまな動作の決定を簡素化する手段としてのポリモーフィズム、複雑さを管理できます。
ソフトウェアの複雑さを管理する他の方法もあります。たとえば、ロジック(プロローグ)や機能(ハスケル)プログラミングなどです。
プログラミングよりも高いレベルでは、OOPを導くためのデザインパターンと原則が必要です。したがって、OOPは低(コーディング)レベルで複雑さを管理していますが、設計パターンや原則などのこれらの方法論は、より高い(システムおよびアプリケーション)レベルでソリューションの設計をガイドし、ソフトウェア開発と処理の複雑さをより管理しやすくします。
あなたの質問に答えるために、はい、OOPは他の多くのソリューションの中で複雑さを処理するための単なるソリューションです。低レベルのソリューションです。OOPをより高いレベルで導くには、デザインパターンと原則が必要です。
オブジェクト指向プログラミングは、必須およびオプションの複雑さを管理しますが、どちらも軽減しません。
The Art of Unix ProgrammingでEric Steven Raymondによって提供された定義が好きです。なぜなら、それは本質的、オプション、偶発的な複雑さを描写しているからです。 http://www.faqs.org/docs/artu/ch13s01.html#id2964646
OOPは、本質的またはオプションの複雑さに対しては何も行いません。これらはプログラムの要件の関数です。OOPを使用すると、よりエレガントなデザインを作成できる場合があるため、偶発的な複雑さに影響を与える可能性があります。ただし、OOPを使用すると設計が悪化する場合があります。
複雑な問題は、テクノロジーを介してよりシンプルに表現することはできず、テクノロジーを介してのみ管理できます。
OOPは、技術、概念、および問題へのアプローチ方法です。
OOPは、複雑さを管理しやすくする設計を実施するためのツールを提供しますが、複雑さを増す悪い設計を簡単に作成することもできます。言い換えれば、適切に使用しないと、問題が技術的に複雑になります。
プロジェクトの成功度を決定する他の多くの側面(プロジェクト管理スタイル、問題定義、変更管理など)があることに留意してください。使用する技術は、問題の管理にどれだけ役立つかという点にのみ関係します。
最終的に、オブジェクト指向プログラミングは複雑さの解決策にはなりません。それを管理するための単なるツールです。(適切に使用した場合)
(従来から使用されている)オブジェクトの向きは、多くの状況で便利なツールですが、複雑さに対する十分な解決策ではありません。
特に、多くの場合、「偶発的な複雑さ」が追加されます。例としては、実装の継承を取り巻く複雑です、「標準機能」イコールとしてSUACH()とhashCode()このトピックに関するスチュワートHallowayが等によりAの素敵なプレゼンテーションをたくさん提供する必要性:「はシンプルで簡単ではありません」
また、ほとんどの言語のオブジェクトは、多くの可変状態をカプセル化する傾向があります -同時進行の世界では、設計の決定が下手に見え始めています。ここでも、Rich Hickeyによる興味深いビデオでは、オブジェクトのアイデンティティと状態の違い、および2つを融合することがどのように間違っているかについて説明しています。
オブジェクト指向プログラミングは、問題を表現する方法であり、それ以上でもそれ以下でもありません。それ自体は、他のプログラミングパラダイムほど複雑ではありません。適切に設計されたOOPシステムは複雑さを管理および軽減しますが、必要以上に複雑ですべての邪魔になるシステムを設計することも非常に簡単です。
C ++についてよく言われているように、OOPを使用すると、自分自身をぶら下げるのに十分なロープが提供されます。
OOPは解決策の試みです。
複雑さを管理する最良の方法は、抽象化を作成することです。それらのコレクションで動作する認識可能な機能を使用して、データを有用なコレクションに変えることができれば、そのコレクションを個別の「もの」として考え始めることができます。それがクラスとメソッドの基礎です。その点で、適切に設計されたOOPは複雑さの管理に役立ちます。
途中で誰かが、OOPを使用してコードの再利用の問題を解決できると判断しました。つまり、なぜ車輪を再発明するのですか?他の誰かがこの問題を解決するために多くの作業を行った場合、その作業を活用し、特定のプロジェクトに必要な調整を追加してください。比較的少しの作業で、強力で洗練されたアプリケーションを作成しました。オブジェクト指向プログラマーは、非常に生産的なプログラマーになることができます。
最終的な結果は、現代のオブジェクト指向プログラマーが「魔術師の見習い」になり、数行の「接着剤」を備えた大量の扱いにくいライブラリーを結び付け、機能するものを手に入れることです。ソータ。ちょっと。ほとんどの時間。このライブラリをそのライブラリで使用することによる潜在的な副作用はありますか?多分。しかし、これらのライブラリに含まれるコードを実際に掘り下げる時間は誰にありますか?特に、ライブラリが進化しているとき。その結果、プログラマーはそのライブラリの少数のクラスとメソッドを必要とする肥大化したアプリケーションになりますが、アプリは必要のないその他すべてのものの重みを担わなければなりません。
最終的には、必要以上に複雑になります。
機能を分離する複雑さを処理する別のメカニズム。すべてのデータアクセス機能が1か所に必要です。すべてのユーザーインターフェイス機能が1か所に必要です。すべてのコントローラーを1か所にまとめる必要があります。したがって、機能のさまざまな部分を管理するさまざまなクラスを作成します。ここまでは順調ですね。そして、これはある程度スケーリングします。データアクセスに精通している開発者がこれらのクラスを作成でき、ユーザーインターフェイスのユーザーがユーザーインターフェイスクラスを作成できます。すべてが順調です。
他の誰かが書いたものを維持する必要があるまで。
はい、すべてのデータアクセス機能がここにあることを知っておくと便利です。しかし、それらは何と呼ばれていますか?
このメソッドは、そのクラスでそのメソッドを呼び出しています。しかし、クラス定義を見ると、その名前のメソッドはありません。ああ、それは、継承チェーンの1つまたは2つ上の層から継承されます。ちょっと待って; そのクラスはインターフェースを実装しましたか?そのインターフェースを実装するクラスはいくつありますか?また、実行時にクラスのインスタンスを「ワイヤリング」するために、複雑なランタイムシステム(Springを探しています)を使用していますか?そのインターフェイスを実装するクラスはどこで使用できますか?
最終的には、正確なことを行う多くの小さな個別のメソッドになります。しかし、これは別のクラスでそれを呼び出します。さらに別のクラスでそれを呼び出します。さらに別のクラスでそれを呼び出します。追加のクラスでそれを呼び出します。特定のタイプの結果を返します。特定のことを行うためにメソッドを呼び出す必要があります。別の型の結果を返します。等。
これには、スパゲッティコードという用語があります。
コードを作成するためだけに必要な非常に複雑なシステムになります。したがって、Visual Studio、Eclipse、NetBeansなどのIDE。すべてに重要な学習曲線があります。実際、それらの多くは異なるグループによって開発された複数のツールをカプセル化/集約することができ、それぞれが独自の学習曲線を持っています。
これは複雑さを管理していますか?
コードのデバッグは、書くよりも2倍難しいです。このようなもののデバッグを頑張ってください。特に、複数のライブラリを使用している場合は、実行時に何らかの依存関係注入システムを使用して「接続」されます。
要約すると、OOPは、複雑さを管理するのに役立つ有望なツールのようなものを提供します。現実には、結果のコードは恐ろしく肥大化する傾向があり(リンクされたライブラリのすべてから必要な部分だけを抽出することはできないため)、コードをナビゲートするためだけに洗練されたツールが必要です。すぐにメンテナンスの悪夢になります。
私見、それは純損失です。排除するよりも複雑さが増します。それなしでは、あなたは非常に困難で、おそらく不可能でさえあることをすることができます。しかし、大規模なプロジェクトはすべて、維持できない混乱に急速に発展します。
それがどのように機能するかをすでに知っていて、それを覚えているなら、あなたはそれを維持する機会を得るかもしれません。
Eaglesonの法則を適用することを忘れないでください。6か月間見ていない独自のコードは、他の誰かによって書かれている可能性があります。
オブジェクト指向プログラミングが複雑さの処理に役立つと思われる理由は、膨大な種類の方法ではなく特定の方法でコードを書くことを強制するためです。タスク指向プログラミングははるかに直感的であり、プログラミングがそのように始まったのはそのためです。オブジェクト指向では、効果的に理解して使用するためにトレーニングと練習が必要ですが、プログラミングを特定のパスに制限することにより、トレーニングを受けた人が作成されたコードを効果的に維持できます。
これは、他のどの方法よりも論理的でも現実的でもありません。同様のレンズを通して問題解決に焦点を当てる方法にすぎません。多くの専門技術は、直感的ではない厳格な方法論のパラダイムを使用して、タスクの複雑さを処理します。
複雑さを処理する3番目の方法は関数型プログラミングであり、将来的には他の新しい方法もおそらく登場するでしょう。