JavaRush /Java Blog /Random-JA /オブジェクト指向プログラミング(記事の翻訳)
Exidnus
レベル 38
Санкт-Петербург

オブジェクト指向プログラミング(記事の翻訳)

Random-JA グループに公開済み
翻訳者より: 残念ながら、私は英語の本をよく読みますが、英語からの翻訳に関してはあまり経験がありません。しかし、読書と翻訳は別のものであることがわかりました。また、残念なことに、私には大きなプログラミング経験がありません (最近、Spring MVC と Hibernate で簡単な Web アプリケーションを作成したばかりです)。したがって、翻訳は予想よりもはるかに悪いものになりました。この記事に記載されているコード例は Java の命名規則に準拠していないため、勝手に少し修正しました。おそらく、いくつかのパターンの名前を翻訳する価値はありませんでしたが (そのような翻訳ではあまり理解が得られません)、これはそれほど害のないものだと思いました。「凝集性が高い」の訳語としての「凝集性が高い」については別途言及する価値がある。私も同意しますが、最良の翻訳ではありません。しかし、「強力な接続性」は「高結合」(もう 1 つの重要な概念)であり、「一貫性」はここでは適切ではないと考えられます。私は批判を歓迎し、いかなる形であっても記事に関するコメントをありがたく受け入れます。 オブジェクト指向プログラミングは、現実世界のオブジェクトに対応するコンポーネントでプログラムが構成されるプログラミング スタイルです。実際のオブジェクトには、プロパティ (時間の経過とともに変化する場合と変化しない場合があります) と動作 (時間の経過とともに変化する場合と変化しない場合があります) があります。他)・条件により変わります)。たとえば、鉛筆は次の特性を持つ現実世界のオブジェクトです。
  • 赤です(時間の経過とともに変化しません)。
  • 現在の長さは10センチです(鉛筆を削れば変わるかもしれません)。
そして、次のような動作をします。
  • 正しく使用すると跡が残ります。
  • 圧力に応じて(外部要因に応じて)トレースが異なる場合があります。
  • 研ぐと長さが短くなります(永続的な動作)。
この例のように、現実世界のオブジェクトは多くのプロパティを持つことができますが、プログラムを作成するときは、必要なプロパティのみを考慮します。オブジェクト指向プログラミングには利点があります。たとえば、現実世界のオブジェクトとプログラムの間の接続を予期した方法で確立することが容易になります。これは、アプリケーションが成長し、多くのオブジェクトが相互にやり取りする場合に非常に役立ちます。これは、客観的な世界の中で責任を分散するのに役立ち、アプリケーション全体を考えることに集中できるようになります。OOP (オブジェクト指向プログラミング)に関連するもう 1 つの重要な機能は、オブジェクトの分類です。世界(現実/仮想)にはオブジェクトが溢れているため、それらを個別に制御することは困難です。黒い鉛筆など、さまざまなオブジェクトとそのプロパティを関連付けるために、これらのオブジェクトを分類する方法が必要です。前の例で使用すると区別がつきません(同じ?)が、別のオブジェクトです。ただし、どちらも鉛筆なので、同じクラス「鉛筆」に属します。一方、ペンは鉛筆によく似ていますが、別のクラスに属します。ただし、ペンも鉛筆も「筆記用具」です。 オブジェクト指向プログラミングには次の原則があります。
抽象化
抽象化は、出来事ではなくアイデアとの相互作用の質、つまり表現的な性質からの自由 として定義されます。これにより、プログラマは、どのようにプログラムするかではなく、何プログラムするかに集中できるようになります。抽象化は、機能を提供するための契約と考えることができます。この概念を使用する場合、実装の詳細は非表示になる場合があります。たとえば、書き込みを行うクラスが必要な場合は、そのクラスに「write」メソッドがあることを確認する必要があります 。抽象的な高レベルのクラスを設計しました。言い換えれば、このクラスは必要な機能を認識していますが、それを実装する方法はこのクラスの範囲外です。これには多くの利点があります。 abstract class writer { write (); }
  • 私たちは、外部機関に対して必要最小限の情報を開示します。これにより、プログラム全体を考えることに集中することができ(これにより、集中的な思考が可能になります)、混乱を回避し、意図しない約束を避けることができます。
  • 実装の詳細が明らかになった場合には不可能となる将来の改善の余地を残しておきます。
継承
一般的な英語での「継承」は「取得し、継承する」という意味です。この言葉は私たちの文化の中に非常に長い間存在していました。祖先は苦労して土地を獲得し、それを子供たちに受け継いできました。自然さえも相続に有利です。身長、肌/目/髪の色など、体のすべてのプロパティ。私たちは両親から受け継いだ遺伝子に依存します。継承により車輪の再発明が防止され、進歩が加速されます。OOPでも同様です。いくつかの基本的なプロパティ/動作を備えた親クラスを作成します。この親から継承するすべてのクラスには、その親と同じプロパティ/動作が含まれます。ただし、継承されたクラスは、より多くのプロパティ/動作を取得したり、動作の実装を変更したりする場合があります。 class WritingInstrument { colour; write() { } } class Pen (child of parent) { inkcolour; } 上の例では、親クラス (WritingInstrument) には「color」プロパティと「write」動作があります。子孫クラス(ハンドル)を宣言した場合、「color」プロパティと「write」動作を再度宣言する必要はありません。これらは継承により「ハンドル」クラスに存在します。ただし、子孫クラスは独自の追加のプロパティ/動作を宣言できます。これを実際にどのように使用できるでしょうか? 私たち開発者はとても怠け者です。何かを何度も印刷したくありません。次の考慮事項により、同じコードの複数のコピーの存在は推奨されません。
  • コードのコピーが少ないほど、保守が容易になります。
  • コードのコピーが少ない場合、1 か所の変更があらゆる場所で確認できるようになります。
  • コードが少ないほど、エラーも少なくなります。
  • 1 つのコードが多くの場所で使用される場合、一般化が達成されます。
  • 私たちはコードを書くことに重点を置いています。
  • 私たちはテストに重点を置いています。
Java での継承は、キーワード「拡張」と「実装」を使用して実現されます。 class WritingInstrument { } class Pen extends WritingInstrument { }
ポリモーフィズム
「ポリモーフィズム」という言葉は、 「Poly」という2 つの単語から来ています。「多くの」/「複数の」 「モーフ」、つまり 「フォーム」 文字通り、「ポリモーフィズム」という言葉は、オブジェクトが条件に応じて異なる動作をする能力を指します。プログラミングでは、ポリモーフィズムをいくつかの場所で実装できます。
  • クラス
  • メソッド
  • オペレーター
上記のすべては、使用される条件、おそらくコンテキストに応じて異なる動作をする可能性があります。これは、クライアント (ライブラリを使用するプログラマ) が多くの細かい点を知る必要がなく、コンテキストから必要な情報を選択することで目的の機能が実装されるため便利です。 Class WritingObject { wrire() { // пишем, используя стандартные (по дефолту) цвета } } class Pencil extends WritingObject { write() { // пишем, используя серый цвет, написанный текст можно стереть } } class Pen extends WritingObject { write() { // пишем, используя голубой цвет, написанный текст нельзя стереть } } class Main { main() { WritingObject wr = new WritingObject(); wr.write(); // первый вызов WritingObject wr = new Pen(); wr.write(); // второй вызов WritingObject wr2 = new Pencil(); wr2.write(); // третий вызов } } 上記の例には、WritingObject のデフォルト実装があり、子孫クラスのpenとpenによって拡張/オーバーライドされます。write() メソッドは Main クラスで 3 回呼び出されます。メソッドが呼び出されるオブジェクトに応じて、毎回異なる実装が呼び出されます。この場合、 write() メソッドは多態性であるため、さまざまな種類の動作を持ちます。
カプセル化
カプセル化は、関連するデータ/機能を 1 つのユニットに収集することとして定義されます。これは、データへのアクセス/変更を容易にするのに役立ちます。たとえば、特定のユーザーが持つすべてのプロパティを出力する必要がある場合、次のオプションがあります。 printUserProperties(userName, userId, firstname, lastname, email, phone, … … ….) すべてのプロパティを取得して、それらを次々に出力するメソッドを作成しました。リスト内の要素の数が増えると、正しいフィールドを識別できなくなり、フィールドを 1 つ追加または削除するとメソッド シグネチャが変更されます。したがって、最近追加したフィールドが必要ない場合でも、このメソッドのすべてのユーザーを置き換える必要があります。コードを読みやすくし、将来の変更を容易にするために、クラス内のプロパティをカプセル化し、それを集合オブジェクトに変換します。 class User { userName userId firstname lastname email phone .. .. .. } printUserProperties(user) {} オブジェクトとは、変数と関連メソッドのソフトウェア バンドルです。プログラム オブジェクトを使用して現実世界のオブジェクトを表現できます。アニメーション プログラム内の本物の犬や、エアロバイク内のソフトウェア オブジェクトとして本物の自転車を想像することができます。OOP では、クラスはオブジェクトを作成し、オブジェクトに初期状態 (変数) を提供し、動作 (関数、メソッド) を実装するための拡張可能なテンプレート (プログラム コード テンプレート) です。SOLID という頭字語は、2000 年代初頭にロバート C. マーティンによって命名された「最初の 5 つの原則」に対してマイケル フェザーによって造られました。これらの原則を一緒に実装することで、プログラマが保守と拡張が容易なシステムを作成できる可能性が高まることを目的としています。SOLID 原則は、リファクタリングを通じて「腐った」コードを削除するために必要なプログラム開発のガイドラインであり、その結果、コードは読みやすく拡張可能になります。これは、アジャイルで適応的なプログラミング戦略の一部です。
単一責任の原則
OOP では、単一責任の原則により、各クラスがプログラムによって提供される機能の一部を担当し、その責任はそのクラスによって完全にカプセル化される必要があると規定されています。そのすべての機能は、この責任と密接に関連している必要があります。
オープン/クローズの原則
OOP では、オープン/クローズの原則により、「ソフトウェア エンティティ (クラス、モジュール、メソッドなど) は拡張にはオープンであるが、変更にはクローズされるべきである」と規定されています。言い換えれば、エンティティは、ソース コードを変更せずにその動作を拡張できるようにする必要があります。
リスコフ置換原理
OOP では代替可能性が原則です。これは、コンピュータ プログラム内の S が T のサブタイプである場合、T 型のオブジェクトは、変更することなく S 型のオブジェクトで置き換えられる (つまり、S 型のオブジェクトを T 型のオブジェクトで置き換えることができる) ものでなければならないと述べています。必要なプロパティ プログラム (精度、タスクの完了など)。
インターフェース分離原理
インターフェイス分離の原則では、クライアント プログラマが使用しないメソッドに依存することを強制されるべきではない、と定められています。この原則によれば、クライアント プログラマが興味のあるメソッドだけを知ることができるように、大きなインターフェイスをより小さく、より具体的なインターフェイスに分割する必要があります。インターフェイス分離原則の目的は、システムを分離した状態に保つことであり、これによりリファクタリング、変更、再デプロイが容易になります。
依存関係逆転の原則
OOP では、依存関係逆転の原理は、プログラム モジュール間の特定の形式の切断を意味します。この原則に従うことにより、アプリケーション アーキテクチャ (ポリシー設定) を形成する高レベル モジュールから依存する低レベル モジュールまで確立された標準の依存関係が反転 (逆転) されるため、変更された高レベル モジュールはアプリケーションの実装の詳細から独立します。低レベルのモジュール。この原則は次のように述べています。
  • 高レベルのモジュールは低レベルのモジュールに依存しないでください。どちらのタイプのモジュールも抽象化に依存する必要があります。
  • 抽象化は実装の詳細に依存すべきではありません。詳細は抽象化に依存する必要があります。
この原則は、高レベルと低レベルのオブジェクトが同じ抽象化に依存するべきであると主張することで、オブジェクト指向設計についての人々の考え方を逆転させます。

GRASPの原則

General Responsibility Assignment Software Patterns (GRASP) は、オブジェクト指向設計においてクラスとオブジェクトに責任を割り当てるためのガイドラインを提供します。
コントローラ
コントローラー パターンは、システム イベントと対話する責任を、システム全体またはユース ケース シナリオを表す非 GUI クラスに割り当てます。コントローラ:
  • これはユーザーと直接対話しないオブジェクトであり、システム イベントの受信と応答を担当します。
  • 1 つの (または相互に関連する多数の) ユースケースのすべてのシステム イベントを処理するために使用する必要があります。
  • これは、システム操作を制御する GUI の背後にある最初のオブジェクトです。
  • 彼は自分で仕事をする必要はなく、彼の仕事は出来事の流れを制御することです。
クリエイター
クリエーター クラスのタスクは、後で使用するためにオブジェクトを作成して開始することです。これは、初期化パラメータと、どのようなオブジェクトが作成されるかを知っています。場合によっては、作成者クラスがアクティブにオブジェクトを作成してキャッシュに配置し、必要なときに 1 つのインスタンスを提供することがあります。
高い凝集力
高い凝集性は評価パターンであり、その目的は、オブジェクトが 1 つの明確なタスクを実行することを目的としており、容易に制御および理解できる状態にオブジェクトを保存することです。通常、高結合は低結合をサポートするために使用されます。一貫性が高いとは、特定の要素の責任が明確に定義されていること (強く関連しており、集中力が高いこと) を意味します。プログラムをクラスとサブシステムに分割することは、システム プロパティの結合性を高めるアクションの例です。一方、疎結合とは、要素に無関係なタスクが多すぎる状況です。疎結合の要素は、理解が難しく、再利用が難しく、保守が難しく、変更が難しい傾向があります。
間接
Roundabout パターンは、2 つの要素間の対話に対する責任を中間オブジェクトに割り当てることで、2 つの要素間の疎結合 (および再利用性) を維持します。例としては、Model-View-Controller (MVC) パターンでのデータ (モデル) とその表示 (ビュー) の間を仲介するコントローラーの導入が挙げられます。
情報の専門家
情報エキスパート (エキスパートまたはエキスパート原則とも呼ばれます) は、誰に責任を委任するかを決定するために使用される原則です。責任には、メソッド、計算フィールドなどが含まれます。責任を割り当てるときにこの原則を使用する場合、主なアプローチは次の一連のアクションです。責任を分析し、責任を果たすために必要な情報を特定し、最後にその情報がどこにあるかを確認します。情報エキスパートの原則を使用すると、それを実行するための責任が最も多くの情報を持つクラスに割り当てられます。
低結合
疎結合は、責任の割り当て方法を指定する評価パターンです。つまり、クラス間の疎結合で、一方を変更しても他方への影響は最小限に抑えられ、再利用性が最大化されます。
ポリモーフィズム
ポリモーフィズムによれば、タイプに基づく動作のバリエーションは、そのバリエーションが発生するタイプに割り当てられます。これは、ポリモーフィックな操作を使用して実現されます。
保護されたバリエーション
Protected Changes パターンは、不安定性の焦点をインターフェイスにラップし、ポリモーフィズムを使用してそのインターフェイスのさまざまな実装を作成することにより、他の要素 (オブジェクト、システム、サブシステム) への変更から要素を保護します。
純粋な製造
純粋な構築には、問題領域の概念を表さないクラスが含まれており、疎結合、高結合、したがって最大の再利用可能性を実現するために特別に設計されています (情報エキスパート パターンによって提供されるソリューションはこれを達成しません)。このようなクラスは通常、ドメイン駆動設計では「サービス」と呼ばれます。

批判

Potok らによる研究では、OOP アプローチと手続き型アプローチの間に大きな違いは見られませんでした。
OOP と他のテクノロジー、特にリレーショナル テクノロジーとの重要な比較は、厳密で広く受け入れられている OOP の定義がないため困難です (Christopher J. Date)
他の言語 (LISP 方言、関数型言語など) と比較して、OOP 言語には独自の利点がなく、不必要な複雑さが生じます。(ローレンス・クラブナー)
オブジェクト指向プログラミングは技術的に脆弱だと思います。それは、単一のタイプ内で異なるインターフェースの観点から世界を部分に分解しようとします。実際の問題に対処するには、マルチソートされた代数、つまり多くのタイプにまたがるインターフェイスのファミリーが必要です。私はオブジェクト指向プログラミングは哲学的に不健全であると考えています。すべてはオブジェクトであると述べています。たとえこれが真実だとしても、あまり面白くありません。すべてがオブジェクトであると言うのは、まったく何も言っていないのと同じです。(アレクサンダー・ステパノフ)
大企業の間で OOP が人気があるのは、「平凡なプログラマーの大規模な (そして頻繁に変更される) グループ」によるものです。OOP によって課される規律により、プログラマーが「過度の害」を及ぼすことが防止されます。(ポール・グラハム)
オブジェクト指向プログラミングでは、名詞が何よりも優先されます。なぜそのような極端な手段を講じて、一部の品詞を台座に置くのでしょうか? なぜある概念が別の概念よりも優先されるのでしょうか? OOP によって、私たちの思考にとって動詞の重要性が突然低下することは不可能です。これは奇妙に偏った視点です。(スティーブ・イエッグ)
Clojure の作成者である Rick Hickey は、オブジェクト システムを現実世界の非常に単純化されたモデルとして説明しました。同氏は、OOP は時間を正確にモデル化できないため、プログラムでマルチスレッドが一般的になると大きな問題が発生することを強調しました。Unix プログラマーでオープンソース ソフトウェアの擁護者である Eric S. Raymond は、OOP が「The One Solution」であるという主張を批判しており、OOP は多層プログラムを奨励しており、それが透明性を妨げていると書いています。反対のアプローチとして、Raymond は Unix と C の例を挙げました。

リンク

マーガレット・ラウズ @ WhatIs.com ウィキペディアによる! (ロシア語版) 継承はポリモーフィズムである SOLID (オブジェクト指向設計) (ロシア語版) 単一責任原則 OOPS に対する議論(ロシア語版) OOPS とは (誇大宣伝なしで) 翻訳: Varygin D.V.
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION