オブジェクト指向言語(Java)を使い始めたとき、私はほとんど「クール」になり、コーディングを始めました。OOPについて多くの質問を読んだ後、つい最近まで本当に考えたことはありませんでした。私が得る一般的な印象は、人々がそれに苦しんでいることです。私はそれを一生懸命だとは思っていないし、天才だとは言わないので、何かを見逃したか、誤解したに違いないと思っています。
OOPの理解が難しいのはなぜですか?理解するのは難しいですか?
オブジェクト指向言語(Java)を使い始めたとき、私はほとんど「クール」になり、コーディングを始めました。OOPについて多くの質問を読んだ後、つい最近まで本当に考えたことはありませんでした。私が得る一般的な印象は、人々がそれに苦しんでいることです。私はそれを一生懸命だとは思っていないし、天才だとは言わないので、何かを見逃したか、誤解したに違いないと思っています。
OOPの理解が難しいのはなぜですか?理解するのは難しいですか?
回答:
私は個人的に、OOPの仕組みを理解するのはかなり簡単だと感じました。私にとって難しい部分は、その「理由」でした。私が最初にそれに触れたとき、それは問題を探す解決策のように思えました。ほとんどの人が難しいと思う理由はいくつかあります:
最初からオブジェクト指向を教える私見はひどい考えです。手続き型コーディングは「悪い習慣」ではなく、一部のジョブに適したツールです。OOプログラムの個々のメソッドは、とにかく手続き型に見える傾向があります。さらに、手続き型プログラミングを学習してその限界が見えるようになる前に、オブジェクト指向は学生にとってあまり役に立たないようです。
オブジェクト指向を本当に理解する前に、データ構造と遅延バインディング/高階関数の基本を知る必要があります。プリミティブを使用して高次の関数/関数へのポインター。
設計パターンは、より高度なものではなく、オブジェクト指向の基本的なものとして教える必要があります。設計パターンは、木々を通して森を見るのに役立ち、OOが実際の問題を単純化できる場所の比較的具体的な例を提供します。さらに、実際にオブジェクト指向を取得すると、ほとんどのデザインパターンが後知恵で明らかになります。
Cat
を継承するクラスについて話すことは有用でも有益でもありませんMammal
。手続き的に記述した実際のプログラムの実際の例を使用してください。単純なデータ構造のように。
まだ言及されていない要因がいくつかあると思います。
まず、少なくともすべてがオブジェクトである「純粋なOOP」(Smalltalkなど)では、数値を(一例のみ)インテリジェントなオブジェクトではなく、不自然な構成に考える必要があります。単なる値-実際には21
(たとえば)実際には単なる値なので。これは、OOPの大きな利点が現実をより厳密にモデリングすることであると言われた場合に特に問題になりますが、最初は現実。
第二に、OOPの継承は、ほとんどの人のメンタルモデルにも非常に厳密に従っていません。ほとんどの人にとって、最も具体的に分類することは、機能するクラス階層を作成するために必要な絶対ルールに近いところにありません。特に、class D
別のものから継承するを作成することclass B
は、のオブジェクトがのすべての特性をclass D
完全に、確実に共有することを意味します。独自の新しい異なる特性を追加できますが、のすべての特性はそのままでなければなりません。class B
class D
class B
対照的に、人々が物事を精神的に分類するとき、彼らは通常、はるかに緩やかなモデルに従います。一例として、人がオブジェクトのクラスを構成するものについて何らかのルールを作成する場合、他のルールが十分に守られている限り、ほとんどすべてのルールが破られる可能性が非常に一般的です。とにかく、実際には破ることができないいくつかのルールでさえ、ほとんど常に「ストレッチ」できます。
たとえば、「車」をクラスと見なします。これは、ことを確認するために非常に簡単です広大なほとんどの人が「車」として考えるものの大半は、4つの車輪を持っています。しかし、ほとんどの人は、3輪だけの車(少なくとも写真)を見ました。適切な年齢の私たちの何人かは、6輪のレースカーなど、80年代前半(またはそれ以降)のレースカーを覚えています。これにより、基本的に3つの選択肢が得られます。
OOPについて教えることは、多くの場合、巨大な分類法の構築に焦点を当てています。たとえば、地球上のすべての既知の生命の巨大な階層、またはその順序の何かの断片です。これは2つの問題を引き起こします。何よりもまず、多くの人々が手元の質問とはまったく関係のない膨大な量の情報に集中する傾向があります。ある時点で、犬の品種をモデル化する方法、および(たとえば)「ミニチュアプードル」が「フルサイズプードル」から継承するか、またはその逆か、または抽象ベース「プードル」があるかどうかについて、かなり長い議論を見ました「フルサイズプードル」と「ミニチュアプードル」の両方を継承するクラス。彼らがすべて無視しているように見えたのは、アプリケーションが犬のライセンスを追跡することに対処することになっていたことでした。
第二に、そしてほぼ重要なことは、目前のタスクにとって重要な特性に焦点を合わせるのではなく、アイテムの特性に焦点を合わせることにつながります。(ほとんどの場合)本当に必要なのは、私たちのニーズを満たす最も単純なモデルを構築し、構築した抽象化に適合するように必要なサブクラスに適合する抽象化を使用することです。
最後に、もう一度言います。私たちは、長年にわたってデータベースが取ったのと同じ道をゆっくりと進んでいます。初期のデータベースは階層モデルに従いました。データのみに焦点を当てる以外に、これは単一の継承です。しばらくの間、いくつかのデータベースがネットワークモデルに従いました-本質的に多重継承と同じです(そして、この角度から見ると、複数のインターフェイスは、気づいたり気にしたりするために、複数の基本クラスとはあまり違いません)。
ただし、かなり前に、データベースはリレーショナルモデルに大部分が収束しました(そして、それらはSQLではありませんが、この抽象化レベルでは、現在の "NoSQL"データベースもリレーショナルモデルです)。リレーショナルモデルの利点は十分に知られているので、ここでは繰り返しません。プログラミングで使用しているリレーショナルモデルに最も近いものはジェネリックプログラミングであることに注意してください(残念ながら、Javaジェネリックという名前にもかかわらず、1つの例では、実際には資格がありません。正しい方向)。
OOPには抽象的に考える能力が必要です。少数の人々、プロのプログラマーでさえ本当に持っている贈り物/呪い。
この方法で基本的な難しさを要約できると思います。
// The way most people think.
Operation - object - parameters
// Example:
Turn the car left.
// The way OOP works conceptually
Object - operation - parameters
// Example:
Car.Turn(270);
確かに、人々は「左」の270としてのマッピングに慣れることができます。そう、「車を回す」の代わりに「車を回す」と言ってもそれほど大きな飛躍ではありません。しかし、これらのオブジェクトをうまく処理して作成するには、通常の考え方を逆にする必要があります。
オブジェクトを操作する代わりに、オブジェクトに実際に自分で物事を行うように指示しています。もう難しくはないかもしれませんが、ウィンドウに自分自身を開くように指示するのは奇妙に聞こえます。この考え方に慣れていない人々は、最終的にそれが何らかの形で自然になるまで、その奇妙さに何度も苦労しなければなりません。
どのパラダイムでも、ほとんどの人にとって、「エッジを越えて」把握するために特定のプッシュが必要です。定義上、これは新しい思考モードであるため、古い概念を手放すための一定量と、新しい概念が有用である理由を完全に把握するための一定量が必要です。
多くの問題は、コンピュータープログラミングを教えるために使用される方法が一般的にかなり貧弱であることだと思います。OOPは今ではあまり一般的ではないので、それほど目立ちませんが、関数型プログラミングではよく見かけます。
重要な概念は奇妙な名前の後ろに隠れています(FP:モナドとは何ですか?OOP:なぜそれらを時々関数やメソッドと呼ぶのですか?)
奇妙な概念は、実際に何をするのか、なぜあなたがそれらを使用するのか、なぜ誰もがそれらを使用すると考えたのかという点ではなく、比phorで説明されていますオブジェクトはアヒルのようなもので、音を立てたり、歩いたり、動物から継承したりできます)
良いものは人によって異なるため、どの生徒にとって何が転換点になるかは明確ではなく、多くの場合、教師は覚えていません。(FP:ああ、モナドを使えば、型自体に何かを隠して、毎回何が起こっているかを明示的に書き出すことなく、それを実行できます。
最悪なのは、質問が示すように、一部の人々はなぜコンセプトが良いのかをすぐに理解し、そうでない人もいるということです。それは本当に転換点に依存します。私にとって、オブジェクトがデータとそのデータのメソッドを格納していることを把握することが重要でした。その後、他のすべてが自然な拡張としてちょうど収まりました。その後、オブジェクトからのメソッド呼び出しは、そのオブジェクトを最初のパラメーターとして静的呼び出しを行うことに非常に似ていることを認識するようにジャンプしました。
後の小さなジャンプは理解を深めるのに役立ちますが、それは「OOPが意味をなさない、なぜ人々はこれをするのですか?」から人を導く最初のものです。「OOPが最高、なぜ人々は他に何かするの?
OOPの基本的な説明は、フィールドでの使用方法とはほとんど関係がないためです。それを教えるためのほとんどのプログラムは、「オブジェクトとしての車、オブジェクトとしての車輪、ドア、およびトランスミッション...」などの物理モデルを使用しようとしますが、シミュレーションプログラミングの不明瞭なケースの外では、オブジェクトは、非物理的な概念を表現したり、間接性を導入したりするために頻繁に使用されます。効果は、人々に間違った方法で直感的に理解させることです。
設計パターンから教えることは、OOPを記述するよりも優れた方法です。抽象的に記述するよりも、実際のモデリングの問題をオブジェクトで効果的に攻撃する方法をプログラマーに示しているからです。
私はほとんどの場合、dsimchaの答えに同意しません。
オブジェクト指向を最初から教えることは、それ自体では悪い考えではなく、手続き型言語を教えることでもありません。重要なのは、オブジェクト指向または手続き型に関係なく、明確で簡潔でまとまりのあるコードを書くことを人々に教えることです。
優れたオブジェクト指向プログラムの個々のメソッドは、手続きをまったく見ない傾向があります。これは、オブジェクト指向言語の進化(C ++を読んでください。これは私が知っている唯一の他のオブジェクト指向言語であるためです)と、その構文が日々複雑になっています(ラムダ、オブジェクトへのLINQなど)。手続き型言語のオブジェクト指向メソッドとプロシージャの唯一の類似点は、それぞれの線形性であり、すぐに変わるとは思いません。
データ構造を理解せずに手続き型言語を習得することもできません。ポインターの概念は、OO言語と同様に手続き型言語にとっても重要です。たとえば、手続き型言語では非常に一般的である参照渡しのパラメーターを渡すには、OO言語を学習するのに必要なだけポインターを理解する必要があります。
デザインパターンはオブジェクト指向プログラミングの初期段階で教えられるべきではないと思います。なぜなら、それらはオブジェクト指向プログラミングの基本ではないからです。設計パターンについて何も知らなくても、間違いなく優れたオブジェクト指向プログラマーになることができます。実際、適切な名前で文書化されていることや、それらについて書かれていることを知らなくても、有名なデザインパターンを使用することさえできます。基本的に教えるべきことは、単一責任、オープンクローズ、インターフェイス分離などの設計原則です。残念ながら、最近のOOプログラマーであると考えている人の多くは、この基本概念に精通していないか、単にそれを無視することを選択しています。
元のポスターの質問に答えるには、はい、オブジェクト指向は手続き型プログラミングよりも理解しにくい概念です。これは、実際のオブジェクトのプロパティとメソッドの観点から考えていないためです。たとえば、人間の脳は「TurnOn」をテレビの方法とは容易に考えていませんが、テレビをオンにする人間の機能と考えています。同様に、多型は人間の脳にとっては異質の概念であり、一般に、現実の各オブジェクトを1つの「顔」だけで見ます。遺伝は再び私たちの脳にとって自然ではありません。私が開発者だからといって、息子が一人になるとは限りません。一般的に言えば、人間の脳はオブジェクト指向を学ぶために訓練される必要がありますが、手続き型言語はそれに自然です。
Objects Neverを読むべきですか?まあ、ほとんどこれまで。(ACMメンバーシップが必要です)Mordechai Ben-Ari氏は、OOPは実際には何かをモデリングするのに自然なパラダイムではないため、OOPは非常に難しいと提案しています。(私はこの記事について留保していますが、プログラムがオブジェクト指向言語を使用した手続き型パラダイムではなく、OOPパラダイムで書かれていると言うためにプログラムが満たす必要があると感じる基準は明確ではありません。)
オブジェクト指向プログラミング自体は難しくありません。
難しいのは、それをうまくやることです。共通のベースオブジェクトに物事を簡単に移動し、後で拡張できるように、コード間にカットを入れる場所はどこですか?他の人がコードを使用できるようにする方法(クラスの拡張、プロキシでのラップ、メソッドのオーバーライド)。
それは難しい部分であり、正しく行われた場合、非常にエレガントになる可能性があり、ひどく行われた場合、非常に不器用になる可能性があります。私の個人的な経験では、それはあなたが十分にそれをうまくやるためには、あなたは違っそれをやってほしいでしょうすべての状況であったとたくさんの練習を必要とすることで、この時間を。
私はリチャード・ファインマンのビデオを見て、人々が思考の際に実際にはまったく異なる方法論を実際に持っているかもしれないことを議論していました-私は完全に異なることを意味します。
高レベルの設計を行うと、たまたまオブジェクトを視覚化することができます。オブジェクトを見て、それらのインターフェースを見て、情報が横断する必要のある経路を見ることができます。
また、詳細を思い出すのに苦労しており、オブジェクト指向は組織的に優れた補助であることがわかりました。サブルーチンの緩やかに組織化されたリストをスキャンするよりも機能を見つける方がはるかに簡単です。
私にとってオブジェクト指向は大きな利点でしたが、同じ方法で視覚化しない場合、または高レベルのアーキテクチャを実行しない場合、それはおそらく無意味で迷惑です。
INSTR
名前がタイプ(のように接続されているので、 - ) string::find
)
OOを紹介する前に、GW-BasicとTurbo Pascalのプログラミングをかなり行っていたので、最初はDIDで頭を悩ませました。
これが他の人に起こるかどうかはわかりませんが、私にとってはこうでした。プログラミングに関する私の思考プロセスは純粋に手続き型でした。「そういうものが起こると、そういうものが次に起こる」などのように。変数やデータは、プログラムの流れのなかで、逃げる行為以上のものとは考えませんでした。プログラミングは「アクションの流れ」でした。
把握するのが容易ではなかったのは(今の私には見えないほど愚かな)、データ/変数が実際に重要であり、プログラムの「フロー」でつかの間の役者であるよりも深い意味でのアイデアだと思います。または、これを別の言い方をすれば、私はそれを把握するための本当の鍵であるものではなく、何が起こるかでそれを理解しようとし続けました。
理解するのは難しいとは思いませんが、クエリを実行するプログラマの多くは、手続き型言語から来た概念に新しい人かもしれません。
私がこれまでに見た/読んだ多くの人々から(少なくともフォーラムで)OOPの「結果」を探します。あなたが戻ってコードを変更しないで手続き型のプログラマーである場合、その利点を理解するのはおそらく難しいかもしれません。
また、多くの悪いOOPが存在します。人々がそれを読んだり見たりしている場合、なぜそれが難しいと思うのかが簡単にわかります。
IMOは、「カチッ」と音がするまで待つか、本当の知識を持っている人から教えられる必要があります。急ぐことはできないと思います。
OOPが多くの人にとって難しい理由は、ツールが実際にそれを促進しないからだと思います。
今日のコンピューター言語は、コンピューターで行われていることの抽象化です。
OOPは、抽象化を表す抽象化された方法です。
したがって、抽象化を使用して、抽象化を使用して抽象化を構築しています。これに加えて、私たちが抽象化しているのは通常、非常に複雑な物理的/社会的相互作用であり、当然のことです。
私は実際に、「オブジェクト指向プログラミングの苦労」と呼ばれるブログを持っています。手続き型プログラミングを使うのに多くの時間を費やしたため、理解するのは特に難しいと思います。また、オブジェクトは属性と動作のコレクションで表すことができるという考えに頭を悩ませるのに苦労しました単に変数とメソッドのコレクション)。
また、言語をオブジェクト指向にするための多くの概念があります-継承、インターフェース、ポリモーフィズム、構成など。実際にコードを効果的に、そしてオブジェクト指向で書く前に、理論について学ぶべきことがたくさんあります。方法ですが、手続き型プログラミングでは、変数のメモリ割り当てや他のメソッドへのエントリポイント呼び出しなどを理解するだけです。
動機。理由が分からないときや、自分がやったことを見て自分が正しくしたかどうかを判断できないとき、何かを学ぶのは難しくなります。
必要なのは、OOを使用して有用なことを行う小さなプロジェクトです。デザインパターンに関する本を調べて、明らかに有用であり、オブジェクト指向でうまく機能するものを考え出すことをお勧めします。(一度試してみましたが、FlyweightやSingletonのようなものは、一般にオブジェクトを使用する方法であり、オブジェクトを使用して何かを達成する方法ではないため、悪い選択です。)
それは年齢(経験の代理としての年齢)、そしてもっと重要なことに興味に依存していると思います。あなたが「若い」(つまり、おそらく緑)であり、他の方法を考えたことがない場合、それは非常に簡単に思えます。一方、これがあなたが今まで見た中で最もクールなものだと思うなら、28歳か何かで私に起こったことは、簡単に理解できることです。
一方、私のJavaの学生の多くが「なぜこれを学んでいるのか、それはただの流行だ」と思うなら、学ぶことは事実上不可能です。これはほとんどのテクノロジーに当てはまります。
どのパラダイム(OOP、機能など)を選択するかに関係なく、コンピュータープログラムを作成するには、プログラムが実行するステップを知る必要があります。
プロセスを定義する自然な方法は、ステップを書き留めることです。大きなタスクの場合、タスクを小さなステップに分解します。これは手続き的な方法であり、これがコンピューターの動作方法です。これは、チェックリストを段階的に実行する方法です。
OOPは別の考え方です。ステップごとに実行する必要があるタスクのチェックリストを考える代わりに、オブジェクト、その能力、関係を考えます。そのため、多くのオブジェクト、小さなメソッドを記述し、プログラムは魔法のように動作します。これを達成するには、心をひねる必要があります...
そして、これがOOPが難しい理由です。すべてがオブジェクトであるため、他のオブジェクトに何かをするように要求するだけで、他のオブジェクトは基本的にいくつかを実行します。そのため、OOPプログラムのコントロールは、オブジェクト間を行き来することができます。
現在、プログラミングを学んでいて、この分野でいくつかの問題を抱えている人として、この概念の具体的な実装がそうであるように、概念を理解するのは難しいとは思いません。OOPのアイデアを得て、PHPで約1年間使用してきたのでこれを言いますが、C#に進み、他のプログラマーのオブジェクトの使用法を見ると、多くの人々がそうすることがわかります私には分からない これが特に、OOPの原則のより良い理解を見つける道に私を導いたのです。
もちろん、問題はネイティブOOP言語の経験の不足である可能性が高く、時間が経つにつれて、私と同じくらい新しいプログラマーと同じくらい明確ではないオブジェクトを利用する新しい方法を見つけることに気づきます現在経験しています。ジェリー・コフィンはこれについて、特に彼のコメントで数回触れています。
これは、OOPの大きな利点が現実をより厳密にモデリングすることであると言われた場合に特に問題になりますが、最初は現実。
これは非常に正確だと思います。実際にはそうではないもののためにクラスを作成している人を見たときによく受ける印象です-特定の例は私を免れますが、その場で思いつく最も近いものはオブジェクト(次回、同じ混乱を引き起こす何かを見たときに編集します)。時々、OOPは一時的に独自のルールを無視するように思われ、直感的ではなくなります。これは、オブジェクトがオブジェクトを生成しているとき、それらをカプセル化しているクラスから継承しているときなどに頻繁に発生します。
私のような人にとっては、オブジェクトの概念を複数のファセットを持つものと考えるのに役立つと思います。わずかなパラダイムシフトを伴う距離のようなものは、理論上の対象として出会う可能性がありますが、手に持つことができるものではありません。プロパティのセットを持っていると考えなければなりませんが、プロパティへのアクセスなど、より抽象的な動作のセットを持っています。これが私の理解の鍵であることは前向きではありませんが、それが私の現在の研究が先導しているところのようです。
私にとっての主なジャンプは、OOPの抽象的な概念を理解することでした。今、私はプログラミング全般に非常に慣れていないので、私は1年から1年半の間プログラミングを行ってきました。そのため、OOPの紹介はActionscriptとProcessingを使用して行われました。私が最初にActionscriptコーディングを学んだとき、それはOOPではありませんでした。アクションパネルに直接コーディングすることを学びました。それがプログラミングの基本的な基礎(変数、関数、ループなど)を学んだ方法です。だから、FlashやProcessingのステージに直接何かをすることでそれを学びました。
OOPが登場したとき、オブジェクト内にメソッドとプロパティを作成して使用および再利用できるようにすることを理解することは、最初は理解するのが少し困難でした。すべてが非常に抽象的で処理が困難でしたが、プログラミング言語自体ははるかに優れていましたが、最初にそれらの接続を確立するために一種の信頼が必要になりました。
優れたOOPの理解=優れたメンターまたは優れた書籍、あるいはその両方+個人的な興味+実践。
私の個人的な経験から、個人的な関心は、メンターまたは良い本、あるいはその両方からの適切な入力を使用して、手続き型プログラミングからOOPへの橋を渡る長い道のりを歩みます。
OOPのより良い理解を得るための私の親友は、練習に他なりませんでした。これは間違いなくあなたのOOP能力を育てます。
sayingにもあるように、「ハードワークに代わるものはなく、成功への近道もありません。」
幸運を!