OOPは簡単になりますか、難しくなりますか?[閉まっている]


36

オブジェクト指向プログラミングの概念が何年も前にプログラマーに紹介されたとき、それは興味深く見え、プログラミングはよりきれいになりました。OOPはこんな感じでした

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

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

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

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


23
優れたソフトウェアアーキテクチャを作成することは常に困難であり、常に(おそらく)困難です。
ヨハネス

6
私は名前を変更しますaddItemのためにaddremoveItemのためにremove。読みやすいからです。stock.add(item)または stock.remove(item)。さらに、OOP指向です。
-razpeitia

1
元のOOPは、これまでに示したものとはほとんど似ていませんでした。OOPは構文ではなく、Smalltalkによって普及した一種の抽象化です。これは必ずしもあなたの主張が間違っていることを証明するものでも、前提に欠陥があるわけでもありません。むしろ、あなたが思っている以上に真実です。
コンラッドルドルフ

1
ロジックでリンゴとオレンジを比較している場合、命令型プログラミング(つまり、ループとif条件)は、今日のすべてのものよりも簡単です。命令型プログラミングはクラス/ OOPの構成要素であり、クラス/ OOPは設計パターンの構成要素です。複雑な問題を解決しているため、進行するにつれて事態は複雑になります。
ライライアン

2
@LieRyan-担当者が単純な命令型プログラミングでそれらを解決できず、単独で実装されるべき単純な命令型ソリューションに加えて、OOP上の設計パターンでそれらを攻撃できたからといって、問題が複雑になるのを見てきました。
mouviciel

回答:


35

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

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

1つの理由は、あなたがさらされているコードがより複雑になることかもしれません-OOPがより複雑になったからではなく、学習の梯子を進んで、より大きくより複雑なコードベースを読むようになったからです。

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

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

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


そのため、設計パターンによって複雑さが増しました。意味のあるデザインパターンは必ずしもOOPではありませんが、OOPを強化するために追加されています。
tunmiseのfasipe

@tunmisefasipe:まったく違います。設計パターンは、標準的な問題に対する実証済みのソリューションです。それらはOOPの「追加」ではなく、結果です。複雑さはすでにそこにありました。デザインパターンは、それに取り組むためのクックブック戦略を提供するだけです。
-tdammers

17

いいえ、より過剰に設計されています。そして、あなたは正しいです。SOC ++チャットでは、Javaコードで見られるAbstractSingletonFactoryProxyBeanBridgeAdapterManagersについてよく冗談を言っています。

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

std::stack<int> s;
s.push(5);
s.pop();

4
あなたの投稿からは明らかではありませんが、過剰なエンジニアリングはJava C ++コードの両方で明らかです。それはどちらの言語自体の特性ではなく、プログラマーの練習の特性です...どちらの言語も優れたコードを書くことができますが、どちらにも(IMO)は特に適していません:)
アンドレスF.

12
オーバーエンジニアリングについては、このスレッドは必須です。discussion.joelonsoftware.com
セキュア

3
@AndresF。本当ですが、C ++コードではあまり得られないようですが、Javaと.NETではそうです:MVVMVMMDデザインパターンmsdn.microsoft.com/en-us/magazine/hh965661.aspxを見てください。元のパターンは宣伝されたほど単純ではなかったため、「単純なコード」を取り、デザインパターンを平手打ちして「見やすく」し、デザインパターンに別のデザインパターンを平手打ちする方法の1つの例です。オーバーエンジニアリングはますます一般的になっています。
gbjbaanb

5
私は「becoming」ビットについて議論します。オーバーエンジニアリングはエンジニアリングと同じくらい古いです。
ロボット

4
@AndresF。チャットでは特に反Javaですが、C ++よりも Javaの方が手頃な価格(GC)になるため、オーバーエンジニアリングを奨励していることは事実です。また、よく知られているエンタープライズJavaライブラリがこのスタイルを普及させました。あなた自身。
コンラッドルドルフ

10

あなたが言う「複雑さ」の問題は、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プログラミングほど難しくありません。


リポジトリを設定するために必要な努力を知っています。それを設定した後、再利用可能になりますが。
tunmiseのfasipe

おそらく、問題はユニットテストにあります。小さなピースではなく、(とにかく必要な)全体をテストするためのより良いツールがあれば、バグの少ないシステムがあるでしょうか。
gbjbaanb

2
@gbjbaanb:統合/機能テストと呼ばれるものがすでにあります。ユニットテストは、異なるが同様に必要な目的に役立ちます
ケビン

@gbjbaanb-RailsプラットフォームのCucumberなど、システム全体/受け入れテスト用の優れたツールが既にあります。しかし、チームは非常に優れており、バグをほとんど作成せず、高速で配信します。また、多くの単体テストとシステム全体のテストをいくつか作成します。「テスト三角形」についてはこちらをご覧ください。例:jonkruger.com/blog/2010/02/08/the-automated-testing-triangle
ピート

4

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

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

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

しかし、プログラマーにオブジェクト指向(またはそれに関することは何でも)を紹介すると、例外的な状況が明らかになる傾向があることも理解する必要があります。幸福な道を簡単に説明し、初心者がそれを理解したら残りを心配するのは簡単です。特効薬はありません。ええ、その牧歌的な妄想が破られたとき、物事はいつもより難しく見えると思います...


3

「OOの概要」の例は、実際のアプリケーションよりもはるかに単純です。上記を達成するために必要なクラスは1つだけです。問題は、あまり役に立たないことです。いくつかの設計パターンは(ActiveRecordのように)近づこうとしますが、最終的には、些細でない例には複数のクラスがあります。それは大丈夫です。


また、フレームワークは時間の経過とともに構築されることに注意してください。そのため、プログラミングにはより多くの知識が必要です。また、短時間でより多くのことができるようになります。
ジャンヌボヤルスキー

3

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

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

まとめとして、概念としてのOOP自体がより複雑になっているとは思いません。私たちOOPのユーザーは、それをさまざまな方法で使用することを選択できます。それは良いことです。


明確なポイント。私はヤグニを知っています。KISSとは何ですか?
tunmise fasipe

2
@ tunmisefasipe、KISSは設計原則の略称です。元の単語は「Keep It Simple(愚か)」(ref:en.wikipedia.org/wiki/KISS_principle)ですが、より丁寧な言い回しは「Keep It So Simple」です。
-NoChance

3
@tunmisefasipe-KISS = Keep It Simple、愚か。自分OVER、およびOVER、およびOVERへのフレーズIリピート、そしてそれはまだ常にシンクしていないようです。
マイケルKohne

@MichaelKohne、私たちは皆そうです!物事を単純化できるのは芸術だと思います。E = M C Cは非常に簡潔な形で多くのことを言っています!
-NoChance

3

短い答え:はい。難しい問題に対処するからです。

長い答え(強く偏っている):私にとって、デザインパターンは通常、特定の領域に問題があるパラダイムがあることを示しています。OOPパターンはOOPの問題を処理し(低レベルではJavaパターンはJavaの問題を処理します)、FPパターンはFPの問題を処理します。

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

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

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

PS。はい-回答はOOPに偏っており、ある程度はOOPに「反応している」と認めます。OOPには用途がありますが、それは唯一の究極の解決策ではありません。

PPS。はい-デザインパターンを使用します-OOPプログラミングが最終的に簡単になります。

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


2

文書や例がより現実的になったケースだと思います。

初期のOOPの本(特に初期のJavaの本)は、アプリケーションプログラミングの非常に単純化されたビューを提示しました。「10行のJavaプログラムで銀行口座を引き落とす」の例は、6000行のCOBOLコードで実行されるこの単純なタスクの実例を見たので、特に迷惑でした実行不可能として!)。

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

しかし、たった15行のコードで銀行口座を実行する方法を知りたい場合は、関数型プログラミングがお 勧めです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.