オブジェクト指向プログラミングは複雑さの解決策ですか? [閉まっている

softwareengineering.stackexchange https://softwareengineering.stackexchange.com/questions/16179

  •  22-10-2019
  •  | 
  •  

質問

オブジェクト指向プログラミングは複雑さの解決策だと思いますか。なんで?このトピックは少し議論の余地があるかもしれませんが、ここの専門家からの理由の答えを知る私の意図!

役に立ちましたか?

解決

複雑さの解決策はありません。

「The Mythical Man-Month」で、フレッドブルックスは、プログラミングにおける偶発的な複雑さと本質的な複雑さの違いについて議論しています。偶発的な複雑さは、アイデアを直接表現できないため、言語で追加のコードを書いてテストするなど、ツールと方法によって引き起こされます。新しい方法と技術は、偶発的な複雑さを減らすことができます。私は言語とツールが良いので、25年前よりも速く、より速くプログラムを書くことができます。

本質的な複雑さは、私たちがプログラミングでやろうとしていることは本質的に複雑であり、還元不可能な複雑さがあるという事実に由来しています。この文脈では、「本質的」は、「非常に必要な」のではなく、「物の本質に関連する」を意味します。

したがって、彼は、銀の弾丸がなく、書き込みソフトウェアは引き続き困難であると主張しました。

彼の本を読むことを強くお勧めします。具体的には、シルバーアニバーサリーエディションを追加することをお勧めします。その中で、彼は提案されたソリューションを複雑さのためにレビューし、その影響を考慮します。 (彼が最も効果的だと思うのは、シュリンクラップソフトウェアです。複雑なものを一度書いて、数千または数百万コピーを販売しています。)

現在、オブジェクト指向のプログラミングは、正しく行われた場合、抽象化を作成し、複雑さを隠すことで役立ちます。クラスのオブジェクトには、実装の複雑さを気にすることなく、推論できる特定の定義された動作があります。適切に書かれたクラスは互いに低いカップリングを持っています。また、分割と征服は、それを逃れることができれば複雑さに対処するための優れた方法です。また、それらは互いに非常に密接に関連する一連の機能とデータであるという点で、高い結束力を持っています。

他のヒント

まもなくいくつかのより良い答えが得られると思いますが、ここに簡単な答えがあります。

OOPは、世界の他のすべてをモデル化する方法に近い方法でソフトウェアをモデリングすることにより、複雑さをもたらします。一般的に、壁オブジェクトと相互作用するボールオブジェクトを画像化する方が、一連のルーチンとデータ構造が同じことを行うことを想像するよりも簡単です。

*複雑さを「解決する」ことはできないからです

OOPの現在の主流の定義は、複雑さを管理するための良い解決策ではないと思います。

あなたがそのルーツに戻ると、アラン・ケイは「リスプ」の影響を受けたと思います。

LISPは主流の採用によって破損していないため、おそらくそのコアバリューを節約することができました。そのため、Lispがこの複雑さの問題にどのように取り組むかを見ると、私たちに洞察が得られるかもしれないと思います。そして、私たちはそれを基礎として使用して、複雑さに対処するのにOOPがどれほど有用であるかを判断することができます。

「講義3A:Henderson Escherの例」の終わりを見ると SICP, 、Hal Abelsonは、複雑さはタスクをより小さなサブタスクに分割するのではなく、抽象化の層を作成することによって管理されると提案しています。最高レベルでは、抽象化の低いレベルの解決策の観点から、複雑な問題の解決策を表現します。

OOPはもともと、これらの抽象化の層を作成するメカニズムとして意図されていたと思います。

残念ながら、最近では、OOPは(AB)がSpaghettiコード/構造を作成するために使用されています。

FPSマルチプレイヤーゲーム:例を挙げます。

最高レベルでは、ゲームはマップの周りを走り回り、武器を使用してお互いを撮影する多くのプレイヤーを持たせることで機能します。

次の低レベルでは、地図や武器とプレイヤーについて話さなければなりません。おそらく、ゲームの世界で相互作用する物理的なオブジェクトとしてそれらについて話すことができます。

次の低レベルでは、オブジェクトが物理的にどのように相互作用するか(動き、衝突など)について話すことができます。

などなど。

これが意味すること(そして私はSICPから引用しているようなものです。)は、各レイヤーで特定の問題を解決するだけでなく、問題の近くにある問題のクラスを解決することです。解決しようとしています。したがって、問題の説明にわずかな変更がある場合、ソリューションにわずかな変更のみが必要になる可能性があります。

したがって、OOPを使用する賢明な方法は、抽象化のレイヤーを作成することです。抽象化の各レベルで、すぐにあるレベルの「オブジェクト」を使用して問題を解決します。

これが私が講義から引用していたビットです: http://www.youtube.com/watch?v=cytrfncmqhq

いつものように、私は皆に同意しません。複雑さを管理するためのツールを提供することとはほど遠く、OOPは不十分で数学的に偽のパラダイムであるため、膨大な量の複雑さを生み出します。プログラマーを混乱させず、OOPでモデル化できないOOPで物事をモデル化しようとします。

私の見解では、ここでの独創的な作業は、Meyerのオブジェクト指向ソフトウェア構造です。それは、私が重要であると見なすものを含む一連の要件を詳述しています:閉じられた原則。これは、物事は拡張のために開かれている必要があるが、同時に使用するために閉じている必要があると言います。

マイヤーは、エッフェルで具体化されているように、これらの要件からオブジェクトの方向を導き出します。カプセル化は、閉鎖、継承のオープン性、および言及された「もの」がクラスです。

マイヤーは明らかに間違っていたので、私はこの仕事を良い科学と考えており、彼の仕事の質のために、エラーをピン留めて修正することが可能です。

エラーは、モジュール性の単位をクラスまたはタイプにすることです。それは間違っています、そして確かにそうです。 Meyerでさえ、OOPが1よりも高いアリティの関係を処理できないという問題(共分散問題と呼ばれる)を認識しました(つまり、OOPはプロパティでは正常に機能しますが、バイナリ関係では失敗します)。エッフェルでは、この問題はタイプシステムに不健全になりました!

解決策は非常に明確です。モジュール性の単位は、単一のタイプよりも大きくなければなりません。それはいくつかのタイプとそれらに関連する方法で構成されなければなりません。

この抽象化のモデルが抽象化の数学理論、つまりカテゴリ理論:タイプはカテゴリのオブジェクトであり、メソッド(関数)が矢印であることに裏付けられていることは驚くことではありません。

このモデルでは、の表現 いくつかの タイプは一連の関数に知られています。表現は一般から隠されているため、これはcaPulsationですが、クラスではなくモジュールを使用します。

標準のメタ言語(SML)とOCAMLは、このモデルに直接基づいています。 OCAMLにはクラスとOOPもあります。OOPがプロパティ、別名ダイナミックバインディングでディスパッチを提供するため、役に立たない。しかし、ほとんどの現実世界の問題は関係に関係しており、OCAMLではあまり使用されていない驚くべきクラスではありません。

C ++標準テンプレートライブラリでは、ほとんど使用されていない驚くことはありません。

単純な事実は、OOPは複雑さを処理するための適切なツールを提供することはなく、本当に単純な問題を処理するためのツールを提供することさえありません。代わりに、2世代のプログラマーを誤解させ、混乱させます。支援とはほど遠く、OOPは、C、FortranとCobolが疲れ始めて以来、プログラミングに起こった最も悪と悪いことです。

オブジェクト指向のプログラミングには、1960年代にまでさかのぼることができるルーツがあります。ハードウェアとソフトウェアがますます複雑になるにつれて、管理性が懸念されることがよくありました。研究者は、ソフトウェアの品質を維持する方法を研究し、一部にオブジェクト指向のプログラミングを開発し、強く強調することで一般的な問題に対処するために開発されました プログラミングロジックの個別の再利用可能な単位。

したがって、オブジェクト指向のプログラムは、プログラムが実行するタスク(サブルーチン)のリストと見なされる従来のモデルとは対照的に、相互作用するオブジェクトのコレクションと見なされる場合があります。 OOPでは、各オブジェクトはメッセージを受信したり、データを処理したり、他のオブジェクトにメッセージを送信したりできます。各オブジェクトは、明確な役割または責任を持つ独立した「マシン」と見なすことができます。これらのオブジェクトのアクション(または「メソッド」)は オブジェクト自体に密接に関連しています。

http://en.wikipedia.org/wiki/object-oriented_programming

この懸念の分離は、多型、相続、メッセージの合格、デカップリング、カプセル化などのオブジェクト指向の他の特徴とともに、大規模なプログラムの複雑さを非常に効果的に管理できる論理的および概念的なフレームワークを提供します。

ソフトウェア開発には多くの種類の複雑さがあります。プログラミングレベルでは、OOPはオブジェクトとクラスを使用して問題ドメインをモデル化することにより、複雑さに対処しようとします。よく知られている第一人者は、問題解決は問題を表しているだけで、解決策が表現そのものであると述べた。したがって、クラスを使用した抽象化により、アクセス修飾子とメソッドを使用したカプセル化、関係と再利用のための継承、クラス間の関係とコラボレーションの確立において、同様のオブジェクトの異なる行動の決定を簡素化する手段として、複雑さを単純化する手段として、多型を管理することができます。

また、ソフトウェアの複雑さを管理する他の方法もあります。たとえば、ロジック(Prolog)や機能(Haskell)プログラミングなどです。

プログラミングよりも高いレベルでは、OOPを導くために設計パターンと原則が必要です。したがって、OOPは低い(コーディング)レベルで複雑さを管理していますが、設計パターンや原則などのこれらの方法論は、ソリューションの設計をより高い(システムとアプリケーション)レベルで導き、ソフトウェア開発と取り扱いの複雑さをより管理しやすくします。

あなたの質問に答えるために、はい、OOPは他の多くのソリューションの間で複雑さを処理するための解決策にすぎません。低レベルのソリューションです。 OOPをより高いレベルに導くために、設計パターンと原則が必要です。

オブジェクト指向プログラミング 管理します 本質的かつオプションの複雑さですが、どちらも減少しません。

エリック・スティーブン・レイモンドが提供する定義が好きです UNIXプログラミングの芸術, 、それは、必須、オプション、および偶発的な複雑さの間を描写しているためです。http://www.faqs.org/docs/artu/ch13s01.html#id2964646

OOPは、本質的またはオプションの複雑さのために何もしません。これらはプログラムの要件の関数です。 OOPで時々よりエレガントなデザインを作成できるという点で、偶発的な複雑さに影響を与える可能性があります。ただし、OOPを使用すると、設計が悪化する場合があります。

複雑な問題はテクノロジーを通じてより単純にすることはできません、彼らはしかできません 管理されています テクノロジーを通じて。

OOPは、テクノロジー、概念、および問題にアプローチする方法です。

OOPは、aを実施するためのツールを提供します 設計 これにより、複雑さの管理が容易になりますが、複雑さを高める悪いデザインを簡単に持つことができます。言い換えれば、適切に使用されない場合、問題にテクノロジー誘発性の複雑さを持つことができます。

プロジェクトがどれほど成功するかを決定する他の多くの側面があることに留意してください(つまり、プロジェクト管理スタイル、問題定義、変更管理など)。使用する技術は、どれだけ役立つかにのみ関連しています 管理 問題。

最終的には、 オブジェクト指向プログラミングはaにできません 解決 複雑さに;それはそれを管理するための単なるツールです。 (適切に使用する場合)

オブジェクトの方向(従来型で使用されているように)は、多くの状況で有用なツールですが、複雑さに対する十分な解決策ではありません。

特に、それはしばしば多くを追加します」偶発的な複雑さ「。例は、実装の継承を取り巻く複雑さであり、多くの「標準機能」を提供する必要性です。シンプルさは簡単ではありません"

ほとんどの言語のオブジェクトは、多くをカプセル化する傾向があります 可変状態 - 同時世界では、デザインの決定の貧弱な決定のようになり始めています。再び興味深い リッチヒッキーによるビデオ オブジェクトのアイデンティティと状態の区別と、2つを混同するのが間違いである可能性があることを調べます。

オブジェクト指向プログラミングは、問題を表す方法であり、それ以上のものではありません。それ自体では、他のプログラミングパラダイムよりも複雑ではありません。適切に設計されたOOPシステムは、複雑さを管理および削減しますが、必要以上に複雑ですべての邪魔をするシステムを非常に簡単に設計することも非常に簡単です。

よくC ++について言ったように、OOPは自分自身を掛けるのに十分なロープを提供します。

おもう はい, 、詳細を隠す小さな自己含有「ビルディングブロック」に複雑さをスライスし、それらを使用して必要な機能を作成することができるからといって、段階的にレイヤーごとにレイヤーになります。

分割統治。

OOPは解決策の試みです。

複雑さを管理する最良の方法は、抽象化を作成することです。これらのコレクションで動作する認識可能な機能を備えたデータを有用なコレクションに変えることができれば、コレクションを個別の「もの」と考え始めることができます。それがクラスと方法の基礎です。その点で、適切に設計されたOOPは、複雑さを管理するのに役立ちます。

途中のどこかで、誰かがOOPを使用してコードリューズの問題を解決できると判断しました。つまり、なぜ車輪を再発明するのですか?他の誰かがこの問題の解決に向けて多くの仕事をした場合、彼らが行ったことを活用し、あなたの特定のプロジェクトが必要とする微調整を追加してください!あなたはあなたの側で比較的少ない作業で強力で洗練されたアプリケーションを作成しました。 OOプログラマーは非常に生産的なプログラマーになることができます。

最終的な結果は、現代のOOプログラマーが「魔術師の見習い」になることになっており、そこでは、数行の「接着剤」で大規模で扱いにくいライブラリの束を結び、機能するものを手に入れます。ちょっと。ちょっと。ほとんどの時間。このライブラリを使用することで潜在的な副作用がありますか?多分。しかし、それらのライブラリに含まれるコードを本当に掘り下げる時間があるのは誰ですか?特に図書館が進化している場合。その結果、プログラマーはそのライブラリから少数のクラスと方法を必要とする肥大化したアプリケーションになりますが、アプリは必要ではない他のすべてのものの重みを搭載する必要があります。

最終結果は、あなたが必要とするよりもはるかに複雑になってしまうことです。

機能性を分離したい複雑さに対処する別のメカニズム。すべてのデータアクセス機能が1つの場所で機能する必要があります。すべてのユーザーインターフェイス機能が1つの場所で必要です。すべてのコントローラーが1つの場所で必要です。そのため、機能のさまざまな部分を管理するさまざまなクラスを作成します。ここまでは順調ですね。そして、このスケール、ある程度。データアクセスに熟練している開発者は、それらのクラスを書くことができ、ユーザーインターフェイスの人はユーザーインターフェイスクラスなどを書くことができます。

他の誰かによって書かれたものを維持する必要があるまで。

はい、すべてのデータアクセス関数がここにあることを知っておくのは良いことです。しかし、何がそれらを呼んでいますか?

この方法は、そのクラスでその方法を呼び出しています。しかし、クラスの定義を見ると、その名前の方法はありません。ああ、それは継承チェーンの1つまたは2つのレイヤーの何かから継承されています。ちょっと待って;そのクラスはインターフェイスを実装しましたか?そのインターフェイスを実装するクラスはいくつありますか?そして、私たちはいくつかの複雑なランタイムシステム(私はあなたを見ています、春)を使用して、実行時にクラスのインスタンスを「一緒にワイヤー」しますか?そのインターフェイスを使用できるクラスはどこで使用できますか?

あなたは、正確なことをする多くの小さな個別の方法で終わります。しかし、これは別のクラスでそれを呼びます。さらに別のクラスでそれを呼びます。それをさらに別のクラスで呼びます。追加のクラスでそれを呼びます。特定のタイプの結果を返します。特定のことをするために方法を呼び出す必要があります。別のタイプの結果を返します。等。

これには用語があります:Spaghettiコード。

コードを作成するためだけに必要な非常に複雑なシステムが必要になります。したがって、Visual Studio、Eclipse、NetBeansなどのIDES。これらはすべて、重要な学習曲線を持っています。実際、それらの多くは、異なるグループによって開発された複数のツールをカプセル化/集約することができ、それぞれが独自の学習曲線を持っています。

これは複雑さを管理していますか?

デバッグコードは、それを書く方が2倍です。このようなもののいくつかをデバッグしてください。特に、複数のライブラリを使用している場合は、実行時に何らかの依存関係噴射システムを使用して「Wired Together」を使用しています。

要約すると、OOPは複雑さを管理するのに役立つ有望なツールのように見えるものを提供します。現実には、結果のコードが恐ろしく肥大化する傾向があり(リンクされたすべてのライブラリから必要なピースだけを抽出できないため)、コードをナビゲートするためだけに洗練されたツールが必要です。すぐにメンテナンスの悪夢になります。

私見、それは純損失です。排除するよりも複雑さを増します。それはあなたがそれなしでは非常に困難であり、おそらく不可能でさえあることをすることを可能にします。しかし、大規模なプロジェクトは急速に進化して、維持できない混乱になります。

あなたがそれがどのように機能するかをすでに知っていて、それを覚えているなら、あなたはそれを維持するチャンスに耐えるかもしれません。

イーグルソンの法則を忘れないでください:あなたが6か月で見たことのないあなた自身のコードは、他の誰かによって書かれているかもしれません。

ある程度...

なんで?非常に論理的なモジュール性を促進するからです。少なくとも、スパゲッティコードの巨大な山を書くのが魅力的である手続き上のプログラミングと比較して。

オブジェクト指向のプログラミングが複雑さを処理するのに役立つと思われる理由は、多様な方法ではなく、特定の方法でコードを書くことを強制するためです。タスク指向のプログラミングははるかに直感的であるため、プログラミングがそのように開始されました。オブジェクトオリエンテーションは、効果的に理解して使用するためのトレーニングと練習を必要としますが、プログラミングを特定のパスに制限することにより、訓練された人々が書かれたコードを効果的に維持できるようにします。

それは他のどの方法よりも論理的または現実世界ではありません。それは、同様のレンズを通じて問題解決を集中する方法にすぎません。多くの技術的専門分野では、非直感的な剛性方法論のパラダイムを使用して、タスクの複雑さを処理します。

複雑さを処理する3番目の方法は機能的なプログラミングであり、おそらく将来的には他の新しい方法もあります。

プログラマーとして、データがある場所にメソッドを配置し、アプリケーションのオブジェクトモデルを作成することになっているため、メンテナビリティの解決策だと思います。

はい、それはまた、プロパティと可能なアクションを持つオブジェクトとして、あなたのコードを自然な方法で「見る」モデルを提供することにより、複雑さの解決策でもあります

ライセンス: CC-BY-SA帰属
所属していません softwareengineering.stackexchange
scroll top