web-dev-qa-db-ja.com

OOPは簡単になるか難しいですか?

オブジェクト指向プログラミングの概念がプログラマーに何年も前に導入されたとき、それは興味深く見え、プログラミングはよりクリーンでした。 OOPはこのようでした

Stock stock = new Stock();
stock.addItem(item);
stock.removeItem(item);

わかりやすい名前を付けるとわかりやすくなります。

しかし現在、データ転送オブジェクト、値オブジェクト、リポジトリ、依存性注入などのパターンを持つOOPはより複雑になっています。上記を実現するには、いくつかのクラス(例えば、抽象、ファクトリー、DAOなど)を作成し、いくつかのインターフェースを実装する必要があります

注:コラボレーション、テスト、統合を容易にするベストプラクティスに反対しているわけではありません

36
tunmise fasipe

OOP自体は、当初からそれほど変わっていません。それに対するいくつかの新しい角度が検討されてきましたが、コアの原則はまだ同じです。どちらかと言えば、長年にわたって集められた集合的な知識は、プログラマーの生活を難しくするのではなく、より簡単にします。デザインパターンは障害ではありません。それらは、長年の経験から抽出された、標準的な問題に対するソリューションのツールボックスを提供します。

それでは、なぜOOPを今日使い始めたときよりも複雑だと感じているのですか?

1つの理由として、公開されているコードがより複雑になったことが考えられます。OOPが複雑になったためではなく、ラーニングラダーが進歩し、より大きく複雑なコードベースを読み取るようになったためです。 。

もう1つの理由は、複雑さのパラダイムは変わっていませんが、平均的なソフトウェアプロジェクトのサイズと複雑さは変わらない可能性があるためです。 serverで20年も経たないうちに開発者の夢だったはずの顧客グレードの携帯電話で利用可能な処理能力により、一般の人々は基本的に、最も安価な使い捨てアプリとエントリのための滑らかなアニメーションGUIを期待していますレベルのデスクトップPCは1980年代の「スーパーコンピューター」よりも強力であり、SmalltalkとC++の初期の頃から水準が引き上げられているのは当然です。

そして、現代のアプリケーションでは、同時実行性と並列性は例外ではなく標準であり、アプリケーションはさまざまなマシン間で通信して、プロトコルのZoo全体を出力および解析する必要があることが多いという事実があります。 OOPは組織のパラダイムとしては優れていますが、他のパラダイムと同様に制限があります。たとえば、同時実行性の多くの抽象化は提供されていません(ほとんどの実装は、後から考えられますが、または完全にライブラリにアウトソーシングされます)、そしてそれはパーサーを構築してデータを変換するための最良のアプローチではありません。現代のプログラミングはOOPパラダイムの制限に頻繁に遭遇し、設計パターンはこれまでのところしか利用できません。 (個人的に、私はデザインパターンが必要であるという事実をこれの兆候と見なします-パラダイムがこれらのソリューションを箱から出して提供した場合、これらの問題に対してより表現力があり、標準的なソリューションは明白になります。 OOPのコア機能であるため、メソッドの継承を説明するデザインパターンはありませんが、OOPは、オブジェクトを多態的かつ透過的に構築する明白な自然な方法を提供しないため、ファクトリパターンがあります。

このため、最新のOOP言語には他のパラダイムの機能が組み込まれており、より表現力があり、より強力ですが、より複雑にもなっています。 C#はこのための主要な例です。これには明らかなOOPルートがありますが、デリゲート、イベント、型推論、バリアントデータ型、属性、匿名関数、ラムダ式、ジェネリックなどの機能は他のものに由来します。パラダイム、特に関数型プログラミング。

35
tdammers

いいえ、それはより過剰に設計されてきています。 SO C++チャットでは、Javaコードに表示されるAbstractSingletonFactoryProxyBeanBridgeAdapterManagersについて頻繁に冗談を言っています。

しかし、優れたコードはこの特性を示しません。良いコードでは、あなたはまだ言うことができます

std::stack<int> s;
s.Push(5);
s.pop();
17
DeadMG

おっしゃる「複雑さ」の問題は、OOPとは何の関係もないと思います。それは関心事を分離することにもっと関係があります。

何年も前に、ドメインクラスがデータベースから自分自身をロードする責任を負うシステムに取り組みました。

var userId = Request.QueryString["UserID"].ToInt();
var user = new User(userId);
user.Name = ...;
...
user.Save();

これは非常に明確なコードです。これを理解しても問題ありません。ただし、問題はコードの単体テストにあります。つまり、Userクラスをデータベースからロードせずに単体テストするにはどうすればよいですか?また、データベースにアクセスせずに、このWebリクエスト処理コードをどのようにテストしますか?それは単に不可能です。

そのため、ドメインロジックをユーザーから処理する責任と実際にデータストアにデータをロードおよび保存する機能を分離するために、リポジトリのようなパターンがあります。 IOCは、カップリングの削減、コードのテスト性の向上などに役立ちます。

それで、あなたが書いた例に戻ると、それを作成した後、そのストックをどうしますか?データベースに保存します

Stock stock = new Stock();
stock.addItem(item);
stock.removeItem(item);
this.StockRepository.Add(stock);

やった! OOPの進行に動きはありません。これは難しいことを示唆しています。残念ながら、データアクセスにORマッパーを使用することを選択した場合コード、ORマッパーがシステムの記述方法に制限を課しているという問題に遭遇する可能性がありますが、それは別の問題です。

これらのパターンに慣れていない場合は、新しいスタイルのプログラミングを学ぶ必要があるかもしれません。しかし、そのプログラミングスタイルは、昔ながらのOOPプログラミングよりも難しくありません。

10
Pete

どちらでもない。私たちの問題は実際には変わっていません。許容可能なコードの基準が引き上げられました。

上記を実現するには、いくつかのクラス(例えば、抽象、ファクトリー、DAOなど)を作成し、いくつかのインターフェースを実装する必要があります

haveを実行する必要はありません。しかし、そうしないと問題が発生します。常にそこにあった問題。しかし、プログラマーはそれらの問題を特定し、それらを軽減するためのメカニズムを提供する(必要な場合)ための十分な経験があります。私たちはそれらについてさらに学び、より良い解決策を考え出します(たとえば、シングルトンに対するプログラマーの見解を参照)。

しかし、OO(またはそのことについては何でも)をプログラマーに紹介することは、例外的な状況を覆い隠す傾向があることも理解する必要があります。ハッピーパスを説明し、残りの部分を心配するほうが簡単です。初心者がそれを落としたら、銀の弾丸はないので、ええ、私はその素朴な妄想が破られると常に物事はseemより難しくなると思います...

4
Telastyn

「OOの紹介」の例は、実際のアプリケーションよりもはるかに単純です。上記を達成するために必要なクラスは1つだけです。問題は、それがあまり機能しないことです。一部のデザインパターン(ActiveRecordなど)は近づこうとします。しかし、結局のところ、自明ではない例には複数のクラスがあります。それは大丈夫です。

3
Jeanne Boyarsky

OOを使用するプログラミング言語は、今日変化し続ける複雑な要件と環境に対応しようとしています。OOを使用すると、採用者はさまざまなレベルの複雑さを隠すことができます(他の機能の中でも特に)コーディングがより明確になり、構築と理解がより容易になるようにします。ただし、この機能は必ずしもすぐに使用できるわけではありません。例では、OOコレクション内のアイテムを管理するメソッドを提供することによって私からの詳細。 "AddItem"メソッドを使用してそれを永続化することもできます。複雑さを隠すために費やす努力は、使いやすく、再利用可能なフレームワークをもたらし、人生をよりシンプルにします。たとえば、多くのORM実装を使用すると、プログラマーがSQLの詳細を記述しなくてもデータベースと通信できます。

あなたが参照するパターンはそれだけです。彼らはあなたの人生を容易にすることになっています。しかし、それらを採用して調整するのはあなた次第です。より多くの作業が必要であるという事実は、あなたがより多くの利益を得るからです。それはフェラーリにもっとお金を払うようなものです。あなたがそれらを支払う追加料金が必要な場合。したがって、複数のサーバーと異なるバックエンドデータベースで実行できるスケーラブルなN層ソリューションを構築する場合は、それにコストがかかります。アプリケーションがこの複雑さを必要としない場合、余分な部分を無視して、ニーズをカバーする最も単純なソリューション(KISSおよびYAGNI)にフォールバックします。

まとめると、OOPコンセプト自体がより複雑になっているため、OOPのユーザーはさまざまな方法で使用し、それは良いことです。

3
NoChance

短い回答:はい、難しい問題に対処するためです。

長い回答(強く偏った):私にとって、設計パターンは通常、特定の領域で一部のパラダイムに問題があることを示しています。 OOPパターンはOOPより低いレベルではJavaパターンはJavaの問題を処理します)の問題を扱います、= FPパターンはFPなどの問題に対処します。

プログラミング中は、優先順位が異なる場合があります。あなたは正しいプログラムを持ちたいかもしれません、あなたは市場投入までの時間を短縮し、可能な限り最速のプログラム、長期保守性、または新規採用者による即時保守性を持ちたいかもしれません。あなたがいる茂みに応じて、あなたは大きく異なります-発電所のコントローラーをプログラミングしている場合、最初は正しくそれをしたいのですが、時々バグ修正をしません(「メルトダウンは押すたびに発生します Ctrl+Alt+Del? ")。HPCを使用している場合、ロジックは比較的単純ですが、できるだけ速く実行したい場合などがあります。さらに、一部のパラダイムは、特定の問題(AIとロジックのプログラミング、データおよびリレーショナルデータベースなど)に適しています。

OOPは、単純なケースでは「良すぎる」というものを拡張するものであり、「実際のライブモデリング」の物語です。たとえば、OOPに関する最初の本では、クラスPersonEmployeeManageris-a 関係。これまでのところ良好ですが、従業員がマネージャーに昇格した場合はどうなりますか?

一方、他のパラダイムでは、最初のレッスンが難しいです。たとえば、FP不変変数を使用しています(面白いことに、プログラミングの経験がある人は、これを習得する人よりも学ぶのが難しいことがよくありますが第一言語です)-しかし、最終的にはOOPよりも難しくありません。純粋な関数のテストは簡単で、Haskell/Scala /で...テストを生成するツールがあります。

PS。はい-答えはOOPに対して偏っています。私はある程度、それがOOPに「反応」していることを認めます。OOPには用途がありますが、私の意見では唯一の究極の解決策です。

PPS。はい-デザインパターンを使用します。これにより、OOPプログラミングが最終的にシンプルになります。

PPPS。 OOPの同義語としてOOP命令型プログラミングを使用しました。

3

ドキュメントや例がより現実的になるケースのほうが多いと思います。

初期OOP本(特に初期Java本)は、アプリケーションプログラミングの不合理に簡略化されたビューを提示しました。「10行の銀行口座からの借方Javaプログラム)の例は、6000行のCOBOLコードまで実行するこの単純なタスクの実際の例(およびJava 3500行まで実行する置換の試み)を見たので、常に特に煩わしいものでした。それが実行不可能として放棄される前に!).

ありがたいことにOO本は現在、現実の複雑さを認める傾向があり、それらに対処する方法の有用な例を提供しています。

しかし、銀行口座を15行のコードで実行する方法を確認する場合は、 関数型プログラミング が最適です。

2
James Anderson