おそらく、オブジェクト指向パラダイムを使用する最大の約束は、コードの再利用です。これが達成されたといういくつかの論争。それはなぜ達成されなかったのですか?
コードはOOPとして再利用され、プロジェクトの生産性を高めますか?
またはより扱いやすいですか?またはメンテナンスが簡単ですか?それとももっと質の高いものですか?
コードの再利用は良いことだと私たちは皆同意しますが、この目標を達成するにはいくつかの方法があります。問題は、OOPが提供するコードの再利用方法についてです。いいことでしたか? コードの再利用を実現するためのより良い方法はありますかオブジェクト指向、サブクラス化、ポリモーフィズムなどよりも優れていますか?どんな方法が良いですか? なぜ?
OOP再利用または他のパラダイムの再利用に関する経験を教えてください。
コードの再利用はかなり良い考えです。 素晴らしいものではありません。
「再利用」しようとする約30年のソフトウェアエンジニアリングの視点を私は持っています。
70年代前半に構築した1つのOSの設計を70年代後半に構築した別のOSに再利用したことを発見した後、80年代に「コードの再利用」の調査を開始しました。
コードの再利用の優れた点は、正直なところ、既存のコードを時々再利用できることです。しかし、世界はコードがいっぱいです。どのようにしてあなたが欲しいものを見つけることができますか?これが私がReuse Curseと呼ぶものです:
私はサンタクロースです(オープンソースです)、10億のソフトウェアコンポーネントのバッグを持っています。どれでもかまいません。
幸運を選んでください。
再利用の問題をうまく解決するには:
何年にもわたって発見されてきたことのほとんどは、コードを再利用可能にするためには、その目的のためにコードを設計する必要があるか、暗黙の仮定が多すぎるということです。最も成功したコード再利用ライブラリは実際にはかなり小さいものです。間違いなく、ライブラリとフレームワークは「再利用可能な」コードであり、非常に成功しています。 JavaとC#は、それらがかなり優れたコンピュータ言語であるという理由だけでなく、適切に設計、実装、文書化された膨大なライブラリを利用できるために成功します。しかし、人々はソースコードをライブラリ;それらは、よくドキュメント化されたAPI(一般的に使用できるように設計されています)を呼び出すだけです。
コードの再利用で行われていない(OOPでもない)ことで、システムのコーディング能力が大幅に向上します。
コードには多くの仮定が組み込まれているため、あらゆる種類のコードの再利用が根本的に制限されていることが重要な欠点だと思います。コードを小さくすると、想定を最小限に抑えることができますが、ゼロから構築するためのコストはそれほど大きくなく、再利用による効果は効果的ではありません。コードチャンクを巨大にすると、新しいコンテキストではほとんど役に立たなくなります。ガリバーのように、彼らは100万の小さなひもでビーチに縛られており、あなたはそれらすべてを切る余裕はありません。
私たちが取り組んでいるのは、知識を再利用してコードを構築することです。これが可能であれば、その知識を適用して、必要なコードを構築し、現在の一連の仮定を処理することができます。
これを行うには、ソフトウェアコンポーネントを特徴付ける同じ仕様機能が必要です(必要なことを言う必要があります!)。ただし、この「構築」知識を仕様に適用して、必要なコードを生成します。
コミュニティとして、私たちはまだこれが得意ではありません。しかし、人々はいつもそれをしています。なぜそれを自動化できないのですか?多くの研究があり、これは多くの状況でそれが可能であることを示しています。
これに必要な主要な機構の1つは、「コンポーネントの説明」(これらは単なる正式なドキュメントであり、プログラミング言語のように解析できます)を受け入れて適用する機械的ツールです プログラム変換 彼らに。
コンパイラーはすでにこれを行っています:-}そして、彼らは彼らが取り組む問題のクラスで本当に優れています。
コード生成を備えたUMLモデルは、これを行う1つの試みです。あまり良い試みではありません。ほとんどのUMLモデルで「私はこのようなデータを持っている」と言っています。機能が省略されている場合、実際のプログラムを生成するのはかなり困難です。
実用的なプログラム変換システム、DMSと呼ばれるツール を構築しようとしています。プログラム変換を適用してコードを生成するための仕様を抽象化するのではなく、従来のコードに適用してクリーンアップすることで、かなり注意散漫になりました。 (これらは抽象的に同じ問題です!)。 (そのようなツールを構築するにはかなりの時間がかかります。私はこれを15年間行っており、その間はあなたが食べなければなりません)。
しかし、DMSには、上で説明した2つの重要な特性があります。任意の正式な仕様を処理する機能と、「コード生成の知識」を変換としてキャプチャして、オンデマンドで適用する機能です。そして驚くべきことに、いくつかの特別なケースでは、仕様からかなり興味深いコードを生成しています。 DMSは、主にそれ自体を使用して構築され、その実装を生成します。これにより、(知識)再利用の約束の少なくとも一部が達成されました。非常に大きな生産性の向上です。私には約7人の技術者のチームがあります。 DMSの「仕様」はおそらく1〜2 MSLOCですが、生成されたコードは10MSLOCあります。
要約:世代知識の再利用が勝利であり、コードの再利用ではありません。
コードの再利用はOOPで実現されますが、関数型プログラミングでも実現されます。コードのブロックを取り、コードの残りの部分から呼び出し可能にして、この機能を使用できるようにするときはいつでも他の場所はコードの再利用です。
この1つの呼び出し可能なブロックを変更すると、呼び出されるすべての場所が変更されるため、このタイプのコードを再利用すると、コードが管理しやすくなります。この結果、品質と可読性も向上したと思います。
OOPは単にコードの再利用を提供するためにそこにあります。私はOOPをオブジェクトとやり取りして詳細を抽象化する方法としてより多く見るデータ構造。
オブジェクト指向プログラミングには、1960年代まで遡ることができるルーツがあります。ハードウェアとソフトウェアがますます複雑になるにつれ、管理性がしばしば問題になりました。研究者は、ソフトウェアの品質を維持する方法を研究し、オブジェクト指向プログラミングを開発して、プログラミングロジックの個別の再利用可能なユニットを強く強調することで、一般的な問題に対処しました[要出典]。このテクノロジーは、プロセスではなくデータに重点を置いており、プログラムは自己完結型モジュール(「クラス」)で構成され、その各インスタンス(「オブジェクト」)は、独自のデータ構造(「メンバー」)を操作するために必要なすべての情報を含みます。これは、具体的にはデータではなくモジュールの機能に焦点を当てた長年主流であった既存のモジュラープログラミングとは対照的ですが、コードの再利用とプログラミングロジックの自己完結型の再利用可能なユニットにより同等に提供され、コラボレーションを可能にしますリンクされたモジュール(サブルーチン)を使用する。このより従来のアプローチは、依然として持続し、データと動作を別々に考慮する傾向があります。
はいおよびいいえ
コードの再利用は、多くの異なるアクティビティの包括的な用語です。
私はクリスに同意します。関数型プログラミングはコードを再利用するための良い方法です。
多くのプログラムには、繰り返し発生するコード構造があります。このため、いくつかの設計パターンがOOPの世界で使用されていますが、これは再帰関数および関数型プログラミング言語でのパターンマッチング。詳細については、 実世界の関数型プログラミング の最初の章を参照してください。
OOPの深い継承は多くの場合誤解を招く可能性があると思います。クラスがあり、密接に関連するメソッドの多くが異なるファイルに実装されています。AsJoe Armstrong OOPについて:
オブジェクト指向言語の問題は、これらの暗黙の環境がすべて持ち歩いていることです。バナナが欲しかったのですが、得たのはバナナとジャングル全体を抱えたゴリラでした。
高次関数は、コードの再利用に関しても非常に役立ちます。 map
およびfoldr
これがGoogleの基盤 MapReduce です。
非同期メッセージパッシングも複雑なソフトウェアを整理する良い方法であり、一部のコンピュータ科学者は、オブジェクトが教えて、聞かないでくださいOOP原則。これについての詳細は オブジェクト指向プログラミング:間違ったパス? はJoe Armstrongが引用されています:
私はオブジェクト指向プログラミングとは何なのかと考え始め、Erlangはオブジェクト指向ではなく、関数型プログラミング言語だと思いました。それから、私の論文指導教官は「あなたは間違っている、Erlangは非常にオブジェクト指向だ」と言った。彼はオブジェクト指向言語はオブジェクト指向ではないと述べました。これを信じるかどうかは定かではありませんが、オブジェクト指向プログラミングの3つの原則はメッセージに基づいているため、Erlangが唯一のオブジェクト指向言語であると考えるかもしれませんpassing、オブジェクト間にisolationがあり、polymorphism。
イベント駆動型システムやErlangでの非同期メッセージパッシングは、システムを分離するための非常に優れた方法でもあり、疎結合は複雑なシステムで重要です。十分に分離されたシステムを使用すると、システムを実行しながら、おそらく別のノードでシステムを進化させることができます。 Unibetはこれについて素晴らしいプレゼンテーションを行いました: ドメインイベント駆動型アーキテクチャ
ただし、ほとんどのコードの再利用はライブラリとフレームワークを使用して行われていると思います。
私は長い回答を投稿しますが、なぜですか? Udi Dahanは私よりもはるかによく説明しています。
http://www.udidahan.com/2009/06/07/the-fallacy-of-reuse/
これが投稿の始まりです:
この業界は再利用に夢中になっています。
より多くのコードを再利用しただけなら、すべてが良くなるというこの信念があります。
オブジェクト指向の全体のポイントは再利用であるとまで言う人もいます。そうではなく、カプセル化が大きなものでした。その後、コンポーネント指向は再利用を実現するためのものでした。どうやら、うまくいかなかったようです。サービス指向への再利用の希望をここに留めているからです。
パターンの本全体は、その日の方向性で再利用を実現する方法について書かれています。サービスは、エンティティサービスやアクティビティサービスから、プロセスサービスやオーケストレーションサービスまで、これを実現しようとするあらゆる方法で分類されています。構成サービスは、再利用し、再利用可能なサービスを作成するための鍵として宣伝されています。
汚い小さな秘密についてもお伝えします。
再利用は誤りです
素朴なUNIXパイプは、コードの再利用に関して、他の何よりも多くのことを行っています。オブジェクトは、偶然にコードが構造化された直観的な方法であり、その後、人々は何でもすべてのものに取り掛かり始めました。一般に、オブジェクトはカプセル化のためであり、コードの再利用のためではありません。コードの再利用にはさらに何かが必要であり、クラス継承階層は、コード再利用メカニズムが本来あるべきものの代わりとしては不十分です。
OOPは特別なものではありません。 OOPの有無にかかわらず、再利用可能なコードを作成できます。 純粋な関数は特に再利用可能です:たとえば、Java.lang.math.sqrt(double)
は数値を受け取り、数値を出力します。 OOPはありませんが、他のほとんどのコードよりも確実に再利用可能です。
関数型プログラミングの観点からOOPは主に状態の管理についてです。
関数型プログラミングでは、リストに対して何百もの便利な関数を簡単に作成できます。 http://haskell.org/ghc/docs/6.12.1/html/libraries/base-4.2.0.0/Data-List.html 。
Listクラスには何百ものメソッドがありますか?パブリックメソッドは、小さく保つ必要がある内部状態へのインターフェイスと見なされます。
悲しいことに、多くの小さな関数を(再)使用する代わりに、機能を複製する人もいます。私にとっては、OOPは関数型プログラミングほどにはコードの再利用を促進しないためです。
私にとってはそうですが、常にそうというわけではありません。他の方法で行うこともできました。
ほとんどの場合、抽象基本クラスを作成し、そのクラスの具体的な実装を作成します。
また、多くのフレームワークは継承を利用してコードを再利用します(Delphi、Java、.Netはすぐに思い浮かぶものの一部です)。
それは、多くのユーティリティライブラリとコードのスニペットが同様に仕事をすることができなかったと言っているわけではありませんが、適切に設計されたオブジェクト階層には何か楽しいものがあります。
私の経験では、継承階層のようなOOP原則)を使用した場合よりも、(C++テンプレートなどの)汎用プログラミング機能を通じて「再利用可能な」コードを活用することに成功しました。
OOPは、効果的に再利用するにはオープンすぎます。
再利用する方法が多すぎます。 "私に新しいインスタンスを作成してください!"各パブリッククラスは次のように尋ねます: "call me!"、 "override me!"-再利用のこれらすべての方法はdifferent、それらは異なるパラメーターを持ち、それらは異なるコンテキストで表示され、すべてに異なるルールがあり、それを呼び出す/拡張する/オーバーライドする方法があります。
[〜#〜] api [〜#〜]の方が優れています。これはOOP(またはnon -oop)ポイントですが、実際の生活では、APIは過剰に機能し、成長し続けています。接続ポイントはまだ多すぎます。また、優れたAPIは生活を楽にすることができ、OOPのインターフェースを提供する最良の方法です。
Datadlowパラダイムは、コンポーネントに厳密なインターフェイスを提供します。コンポーネントには次のタイプのポートがあります。
ドメインによっては、いくつかのパケットタイプがあるため、コンシューマとプロデューサは、同じ(または互換性のある)ポートがあれば接続できます。その中で最も美しい部分は、視覚的に実行できることです。接続にパラメータや調整がなく、コンシューマとプロデューサを接続するだけです。
私は少し不明確でしたが、 StackOverflowの "dataflow"タグ 、または Wikipedia "datafow programming" またはWikipedia "flow-based programmingを見てください。 " 。
(また、C++でデータフローシステムを作成しました。したがって、OOPおよびDFは敵ではありません、DF上位レベルの編成方法です。)
CommonLispには、再利用を実現するための多くの手段があります。
動的型付け、デフォルトでコードを汎用にする
命令型の抽象化、つまりサブルーチン
オブジェクト指向、多重継承and複数のディスパッチ
構文の抽象化、新しい構文構造を定義したり、ボイラープレートコードを省略したりする機能
関数の抽象化、クロージャー、高次関数
CommonLispの経験を他の言語と比較しようとすると、コードの再利用を容易にする主な機能は、bothオブジェクト指向および機能的抽象化の存在です。それらは代替よりも補完的です:それらの1つがなければ、不必要な機能を不格好な方法で再実装することを余儀なくされます。たとえば、拡張できないメソッドディスパッチを取得するためのクロージャおよびパターンマッチングとして使用されるファンクタクラスを参照してください。
OOPはmoreコードを再利用する方法を提供します。以上です。
人々がそれを説明する方法を「再利用」するようなものは本当にありません。再利用は、何かの偶発的プロパティです。それを計画するのは難しい。 「再利用」について話すとき、ほとんどの人が意味するのは「使用」です。それははるかに魅力的で刺激的な言葉ではありません。ライブラリを使用するときは、通常、それが意図された目的に使用します。あなたはnot本当にクレイジーなことをしていない限り、それを再利用しています。
その意味で、現実世界での再利用とは、物事を転用することです。ここでこれらの座席を再利用して、座席を並べ替えて...ベッドにすることができます。とても快適なベッドではありませんが、私はそれができます。それは彼らの主な用途ではありません。私はそれらを元の適用範囲外で再利用しています。 [...]明日、イギリスに戻ります。 not飛行機を再利用します。私はそれが意図された目的のためだけにそれを使用します、それについて空想的で刺激的なことは何もありません。
—ケブリン・ヘニー
クラシックOOは、特にクラス間で実際の機能を共有するためのより良い方法がないためにすべての継承に夢中になっている場合、コードの再利用に不十分な場合があります。この問題のために、水平再利用メカニズムが作成されました。 AOP、特性および移植片として。
私はAOPをOOPの欠けている半オレンジ色と見なしています。 AOPは実際にはそれほど知られていませんが、製品コードに含まれています。
簡単な言葉で説明しようと思います。アスペクトと呼ばれる特別な構造で機能を注入およびフィルタリングできることを想像してください。これらのアスペクトには、何がどのように影響を受けるかを定義する「メソッド」があります reflection しかし、コンパイル時に、このプロセスは weaving と呼ばれます。
例としては、「getで始まる特定のクラスのすべてのメソッドについて、取得したデータと取得した時刻をプログラムがログファイルに書き込む」という側面があります。
AOPについて理解を深めたい場合は、この2つの講演をご覧ください。
Traits は、OOPを補完する再利用可能なコードを定義するためのもう1つの構成です。これらは mixins に似ていますが、よりクリーンです。
それらを説明するのではなく 素晴らしいPHP両方を説明するRFC があります。特性はPHPところで、すでにトランクにコミット。
私の意見では、OOPはモジュール化の鍵ですが、今日でもよく知られているようにOOPはまだ不完全です。
私はあざ笑って告白するつもりです、私はOOPをごく最近使用しました。それは自動的には私に来ません。私の経験のほとんどはリレーショナルデータベースを含むので、テーブルと結合です。プログラミングに関しては、考え直しをする必要がないように、最初から学ぶ方が良いという主張があります。私にはその贅沢はなく、いくつかの象牙の塔の理論に関する私のキャリアを捨てることを拒否します。他のすべては、私はそれを理解します。
最初はコンセプト全体が意味をなさないと思いました。それは単に不必要で、面倒すぎるように思えました。私は知っています、これはクレイジーな話です。明らかに、何かの利点を理解したり、より良い方法のためにそれを却下したりするには、ある程度の理解が必要です。
コードの再利用には、コードを繰り返さないという意欲、それを達成する方法の理解、事前の計画が必要です。それだけの価値がない場合があると判断したとき、コードの再利用を避けるべきですか?また、厳密にOOである言語はないため、別のクラスからコードを継承する必要があると考えた場合、エラーがスローされます。せいぜい、それらの言語は、実装に役立つ環境を提供します。
OOPの最大の利点は、コードがどのように整理されるべきかについての一般的な受け入れです。それ以外はすべて肉汁です。プログラマーのチームは、すべてのクラスがどのように構成されるべきかについて完全に合意していないかもしれませんが、彼らはコードを見つけることができるはずです。
私はそれがどこにでもあり、時にはそれがどこにでもあることを知るのに十分な手続き型コードを見てきました。
上記の投稿を読んで、いくつかの備考:
問題はもっと微妙です。
したがってOOP自体は、再利用可能なコードを作成するpovから悪くはありません、しかしOOPを使用して作成されるコードの種類は、本質的に再利用が困難です。
また、関数型プログラミングを使用すると、再利用可能なコードになる可能性があります。しかし、締め切りに間に合うように正しい抽象化コードを書くために抽象化を正しくすることは、実行できないかもしれません。そして、「ハーフライト」の抽象化は、より表現しやすくなりますOOPスタイル。そして、コードの再利用が簡単になりがちではありません-抽象化のレベルが高いほど、コードの理解にはプログラマの限られた認知能力からの先行投資が必要になります。
実用的な例として:ゲームコードは、非常にパズル/アルゴリズムのゲームでない限り、これがゲームのコーディングについて考える自然な方法であるため、多くの変更可能な状態を伴います。 OO。そしてもちろん、再利用は困難です。しかし、同じコードに同じ知識が含まれていますOOPなしで再利用するのはさらに困難です。そして、それを機能的なスタイルに書き換えるにはそのコードについての考え方、その背後にある知識を完全に変更する必要があるかもしれません。ええ、結果としてコードの背後にある知識は、OO to FP rewrite多分...しかし、コストは莫大である可能性があり、人が支払う必要がある種類のコストである可能性があります非常にスマートで抽象化されたコードを再利用したいので、逆説的に言えば、技術的には再利用可能であっても、人々はコードを再利用しないことになります。
...これは最後の微妙な問題につながります。コードの再利用はPeople | Codeインターフェイスに関するものであり、コードのみに関するものではありません。 OOPは、このインターフェイスを提供する適切な仕事をします。なぜなら、それは、今日書かれた多くの種類のコードについて多くの人々が考える数とうまく対応するからです。FP再利用しますが、最近は実際に人々が実際に書く必要がある種類のコードを簡単に再利用できませんこれは、必要なコードの種類として変更されます変更を書き込みます。
追伸そして、誰かが「OOは可変状態ではない」と言いたい場合は、OOとすることもできます)...私は「名前空間としてクラスを使用するFP」と呼んでいます。それはあなたのために働き、それはいくつかの言語のモジュールシステムのいくつかの欠点を避け、より再利用可能なコードをもたらすかもしれませんが、それはOO;)ではありません
OOPは、これらのツールを使用しない場合よりも多くの場所で使用できるコードを作成できるようにする一連の便利なツールを提供します。古いオブジェクトを取り込んでPrintIt
関数を記述し、そのオブジェクトに対して.toString()
を呼び出す場合、複数のタイプのオブジェクトを使用して呼び出すとすぐに、そのコードが再利用されます。これらのツールを使用すると、コードの各行でより多くのことができます
関数型プログラミングは現在、流行に敏感な人の間で非常に熱くなっています。 完全に独立したツールセットを提供し、コードの各行でより多くのことを実行できます。それはおそらく良くないか、うまくいきませんが、ツールボックスに別のツールを提供します。
(オブジェクト指向の再利用の全体的なレベルを上げるというクレイジーなアイデアがありました:アイデアは、単一のCustomer
クラスを定義し、それを私たちが書いたすべてのアプリケーションで使用できるということでした。そうすると、アプリケーションは少しだけでしょうあちこちに接着します。これは機能しませんでした。しかし、OO Failed、または再利用に失敗したという意味ではありません。アプリケーション内でのコードの基本的なタイプの再利用により、より多くの処理を行うアプリケーションを作成し、それらをより高速に作成します。)