みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

締切り済みの質問

本当にオブジェクト指向プログラミングっていいのでしょうか?

いつもお世話になっております。
VC++初心者です。

現在、VC++6.0、MFCのソース修正で四苦八苦しています。
(コーディングするよりも。ソースを追うので苦労してます。)
(初心者の私が言うのも難ですが、オブジェクト指向云々言う前に
 ソースのif文節が異常に長かったり、3重以上ループが出てくると
 とても嫌になります、、、)

一般的(?)に、プログラミングは
手続き型プログラミングよりオブジェクト指向プログラミングが
開発効率がよい、と重宝されているようですが、
どうも納得できていません。
(その手の書籍を2,3冊読みましたが消化不良に終わっています。)

個人的には、手続き型プログラミングの方が好きです。
というのも、慣れているからかもしれませんが、
ソースが追いやすいし、見やすいと思います。

逆にオブジェクト指向プログラミングでは、
・継承されすぎると、基本クラスまで追うのが一苦労。
・インスタンスをつくってから、関数を呼ぶのが面倒な気がする。
 (手続き型なら関数呼び出しのみで済みます。)
・インスタンスをdeleteし忘れて、メモリを圧迫する危険がある。
 (ガーベージコレクションというものもあるようですが、
 どこで何を消しているか不安です。)
・ソースを追いにくい(慣れの問題なのでしょうか、、、)

そこでですが、
「手続き型は~~で大変だけど、オブジェクト指向ならこんなにすばらしい」
というような対比的に具体例を挙げて説明されている
書籍、サイトの紹介、または、よい助言を頂けませんでしょうか。

また、上記に伴い、
・手続き型で組んで失敗した例(オブジェクト指向型にすれば良かった例)
・オブジェクト指向型で組んで失敗した例(手続き型にすれば良かった例)
も宜しければ教えて頂きたく、お願いします。
(成功例のみよりも、失敗からの成功例を教えて頂けると嬉しいです。)

長くなりましたが、宜しければご教授下さい。

投稿日時 - 2009-07-24 20:40:53

QNo.5152568

暇なときに回答ください

このQ&Aは役に立ちましたか?

16人が「このQ&Aが役に立った」と投票しています

回答(17)

#8です。まだ、締め切ってなかったんですね。(私的なサイト・ブログを持たない者にとっては、大変有難いもので。)

まず初めに、『本の紹介、リンク』について。

以前にも、Linuxカテなどで他の回答者さんからいろいろと同様のご指摘を受けたのですが、基本的に私が紹介している書籍というのは、自分が所有している物でも何でもなく、中には大型書店でちらっと立ち読みした物なども含まれていて、あくまで「どの本がいいのか迷っている方には、まず最初に立ち読みするための目安としてください。」的なニュアンスがあります。

よって、本当は別にもっといい良書があるのだけれど、それは他の方が既に紹介されているので私の方では割愛し、2冊目、3冊目としてはいいのではないかという感じで、別のをわざと紹介していたりします。

パターン本の良書といったら、やはり結城さんの本ですね。(但し、Java以外の方々にとっては、若干違和感があるのかもしれませんが。)

「増補改訂版Java言語で学ぶデザインパターン入門」
http://www.sbcr.jp/books/products/detail.asp?sku=4797327030

「デザインパターンとともに学ぶオブジェクト指向のこころ」については、私自身、初めて知りました。また、時間的な余裕が出来次第、こちらの方も読み進めていこうかな、と。

>やはり、OOPを理解する為には、デザインパターンやUMLも
>必要となり、私にはかなりOOPの理解する敷居は高いと感じます。

現時点で未だ紹介されていない書籍の一つに、「専門誌」が挙げられます。中には、重要な技術をコンパクトにまとめている物もいくつかあるので、そういったのも利用されたらよろしいかと。

「UML PRESS Vol.1」
http://gihyo.jp/magazine/umlpress/archive/2001/vol01

上記の専門誌の「特集2 身近な例でGoF 総ざらい&サーバサイドJava ぼくにもわかるデザインパターン 」では、主要なGoFパターンについて、1パターンをB5版1ページずつで紹介していて、各クラス図の掲載もあり、ざっと各パターンを把握するにはとても便利な書籍です。結城さんの本みたいに、具体的なソースについての記載は一切ありませんが、言い換えると言語を限定していないということなので、それはそれでいいことなのかなと。

ただ問題は、発売からかれこれ8年以上経つということもあり、Amazonでも中古でしか手に入りません。

ちなみに、以下のサイトでは、pdfファイルとして一般に公開もしているようです。

HOME >> 技術トピックス
http://www.ulsystems.co.jp/technology-topic028-01.html

>OOPを理解していない私には、どの本が良書で悪書か判断できません。
>やはり、良書と呼ばれるものをひたすら読んで、自分に理解できる
>レベルか否か判断して、駄目なら、他の良書と呼ばれるものを
>あさるしかなさそうです。

私の方では、Javaから入ったということもあり、数多くのJava本の中でも特に役に立ったのが「SJC-P」本ですね。

「Sun SJC-P認定ガイド 310-055対応」
http://ec.nikkeibp.co.jp/item/books/P82770.html

仕事をする上でも、必ずしもベンダー資格というのは必須ではないのですが、他のJava本に比べて圧倒的に優れているのは、Javaの言語仕様に関して、体系的に一通り網羅されている点ですね。上記の書籍内でも、hashCode()メソッドの記述があるのですが、該当箇所では、ハッシュコードのアルゴリズムの簡単な説明などが載っていたりしますからね。

実際には、以下の本を購入しまして、サクッと試験の方はPASSしましたが、詳細な記述に関しては上記書籍の方がかなりオススメですね。

「Sunテキスト Sun Certified Programmer for Java 2 Platform 5.0 Exam[310-055]」
http://www.sbcr.jp/books/products/detail.asp?sku=4797332921

投稿日時 - 2009-12-21 03:55:35

ANo.16

オブジェクト指向を学ぶ上で引っかかりそうな謎などについて、ちらほら書いてみました。
質問者さんもいい加減食傷気味だろうなとは思いつつ、結局長文になってしまいました。
申し訳ありませんが、参考になれば幸いです。


■「オブジェクト指向」の説明が収束しないわけ
一口にオブジェクト指向といっても、いくつか流派があります。
この辺、以下のサイトが参考になります。
オブジェクト指向の概念の発明者は誰ですか?
http://d.hatena.ne.jp/sumim/20040525/p1

このサイトを参考にしつつ至った私の結論では、オブジェクト指向の流派は大雑把にC++派、SmallTalk派、JavaScript派の3つに分かれます。
C++派代表はもちろんC++、SmallTalk派では、Macプログラミング界でメジャーなObjective Cがあります。
Javaは、C++をベースにしつつ、ちょっとSmallTalk側に傾いた印象で、C#も基本はJavaを踏襲しています。
JavaScript派はかなり特異なので、あまり混乱することはないと思いますが、C#2.0は若干JavaScriptっぽくなったというウワサです。
参考:
http://www.atmarkit.co.jp/fdotnet/csharp20/csharp20_01/csharp20_01_01.html

それぞれの流派では、中心に据える概念が違います。
C++派ではオブジェクトが中心ですが、SmallTalk派ではオブジェクト間の通信である「メッセージ」が中心です。
また、使う言葉も結構違います。(フィールドとかメソッドとかいうのは、主にSmallTalk流。仮想関数とかメンバとかはC++流)

このため、どの流派に軸足を置くかで、オブジェクト指向の説明(というか解釈)がまず大きく変わります。
さらに、多くの人は、それぞれの流派の概念を混ぜ合わせたり、いいとこ取りをしたり、経験的に有効な手法を組み合わせて身につけていたりするので、その配合割合によっても解釈が変わり得ます。
さらにさらに、ちゃんと理解できてなさそうな著者が書いたような書籍も世に溢れています。
そんな本を読んで、それすらちゃんと理解できないままに、分かったつもりになっている人も大勢います。
カオスもここに極まれり、です。


■本の読み方
そんなわけなので、書籍で学ぶ上での勧めの指針をいくつか。

1.できればC++で説明している本を選ぶ。
最初の頃は、複数の用語が出てくると混乱の元だと思います。
C++で説明している本に絞れば、用語がかなり統一されますので、混乱が減るのではと思います。
また、Javaのオブジェクト指向は比較的C++に近いので、それでもいいかもしれません。
Objective CとかSmallTalkの本は、「自分の中のオブジェクト指向像」が出来ていない間はお勧めしません。
この段階では、とりあえず「メッセージ」を強調した本は避けておくのが吉だと思います。

2.オブジェクト指向に限定せずに読む。
やや回り道ながら個人的にお勧めの方法は、C++設計技法を紹介した本の乱読です。
その中には、オブジェクト指向を生かしたテクニックもあるし、C++特有のものもあるし、C時代から変わらないテクニックも、時代の先端を行き過ぎた変態テクニックもあります。
そんなのをたくさん読んでいくうちに、「あ、こーいうのがC++によるプログラムの組み方なのかなー」と分かってくると思います。
そんな中で、C++によるオブジェクト指向というのも見えてくると思います。
それがおぼろげに見えた段階でオブジェクト指向の良書を読むと、目からうろこがぽろぽろと、面白いほどよく落ちるでしょう。

3.たくさん読む。
「オブジェクト指向」の解釈は無数にあるので、どれが正しいかは自分の目で見極める必要があります。
そのためには、いろんな解釈をみて、それぞれの利点、欠点、矛盾点などを、自分の経験に照らして考えなければなりません。

4.最後に、いろんなオブジェクト指向の本を読む。
Javaの本とか、Objective Cの本とか、SmallTalkの本とか、C++ではない本を読むと、オブジェクト指向の世界が広がります。
中には、C++の主張と全く逆の主張もあったりして、「結局どっちが正しいの?」と言いたくなる事もあります。
結局どっちが正しいのかは自分で考えて判断するしかなく、そのためにはある程度「自分で考える基盤」が必要なので、これはある程度オブジェクト指向が分かってきてからのほうがいいでしょう。


■お勧めの書籍
○Effective C++ (Scott Meyers)
 C++設計技法の決定版。これを読まずしてC++は語れない!
○C++ Coding Standards (Herb Sutter, Andrei Alexandrescu)
 Effective C++並に使える本です。
○C++プログラミングの処方箋 (Stepehn C. Dewhurst)
 内容はそこそこ高度ですが、読みにくくはありません。
 オブジェクト指向に関するトピックがわりと多いです。
○デザインパターンとともに学ぶオブジェクト指向のこころ
 (アラン・シャロウェイ, ジェームズ・R・トロット)
 私の目からうろこを落とした本です。
 ある程度「オブジェクト指向」のイメージができてから読むといいかもしれません。
・Effective STL (Scott Meyers)
 Effective C++と同じ作者による、STL(C++標準ライブラリの一部)を使用する上でのガイドライン。
 ちなみにSTLは非常に有用なクラスライブラリですが、オブジェクト指向ではありません。
・More Effective C++ (Scott Meyers)
 Effective 3部作でもっとも内容が高度な上、奇妙な翻訳も多い。
 内容はいいのですが、読みにくさはピカイチです。
・Exceptional C++ (Harb Sutter)
 C++やオブジェクト指向の設計について、クイズ形式で問題点と解決法を紹介。
 Effective C++よりやや上級?
・Modern C++ Design (Andrei Alexandrescu)
 「いい言葉に力を与えるには悪い言葉も知らなきゃいけないって、でも決して使うなって。」
 そんなバルスな感じの変態テクニックが満載です。
・オブジェクト指向における再利用のためのデザインパターン
 (Erich Gamma, Ralph Johnson, Richard Helm, John Vlissides)
 通称GoF本。その偉大さはGoogle先生に聞いてみてください。
・リファクタリング (Martin Fowler)
 通称リファクタ本。オブジェクト指向に関する名著の一つです。
・パターン指向リファクタリング入門 (ジョシュア・ケリーエブスキー)
 GoF本、リファクタ本と合わせて3部作なイメージです。セットでどうぞ。

○をつけたのが特にお勧め、・をつけたのは、その後で読んでみるといいかもです。
アジャイル関連の本は、SmallTalkの息がかかっていることが多いように思うので、最初のうちはあまりお勧めしません。
もちろん、わかって読めば非常に有用ですが、オブジェクト指向の初学者には混乱を招く要素が多い気がします。
なお、『C++プログラミングの処方箋』の「全宇宙的なクラス階層」という項目では、他のオブジェクト指向言語では常識である「Objectクラスを頂点とするクラス階層」を完全否定しています。
こういう矛盾に気付いて行き詰まったら、とりあえず深く考えずに次へ進むことをお勧めします。
その後数冊読んだ後で再び読み返してみると、すんなり分かるってことも多いものです。
ちなみに、全宇宙的なクラス階層に関する見解の相違については、C++がオブジェクト指向【専用】言語ではないと分かれば納得できます。


■お勧めできない書籍
『憂鬱なプログラマのためのオブジェクト指向開発講座』
通称憂鬱本。ツッコミどころ満載です。逆にお勧めです!
ただ、悪書も悪書で読んでみてもいいかもしれません。
良書or悪書と人が言ったから、というのではなく、自分で判断できるようになるために、清濁併せ呑み皿まで食らって、自分の頭で考える、というのが、迂遠ながらもやっぱり通るべき道かな、と思います。


■手続き型は大変だけど、オブジェクト指向はすばらしい例
オブジェクト指向の本では、たまにこういう比較をしているものがありますが、その手の本には正直眉をひそめたくなるものが多いです。
よくあるのは、非オブジェクト指向の設計を極端に貶めている例。そして、オブジェクト指向を過度に賛美している例。
とりあえず憂鬱本の作者はC言語に謝れと言いたい。
多分、これらを平等に比較するのはかなり難しいんだと思います。
『オブジェクト指向のこころ』では、(あくまで主観ですが)あまり不自然でない形で機能分割、従来のオブジェクト指向、正しいオブジェクト指向の3つの設計を比較しています。


■そもそもオブジェクト指向の利点とは?
私の理解では、オブジェクト指向というのは「変更に強いプログラムの作り方」です。
だから、オブジェクト指向設計が成功したかどうかは、実際に仕様変更の波に晒してみないと分かりません。
オブジェクト指向では、「変更がなさそうな部分」と「変更がありそうな部分」を分析し、変更がありそうな部分に対して、ありうる変更を施しやすいように設計します。その読みが外れていれば、いかにオブジェクト指向で作ろうが、ダメ設計になります。
しかし、上手く設計すれば、機能分割による設計よりも変更箇所を局所化できます。
つまり、出来上がったプログラムに対して仕様変更要求が発生したときに、オブジェクト指向は真価を発揮します。
言い換えれば、仕様変更がないものや、変更するより作り直したほうが早いような小さなプログラムでは、特に利点はありません。

なお、オブジェクト指向に限らず「複雑な設計を整理して、単純化するための仕組み」というのは、それ自体も若干複雑なものです。
それによって増える複雑さよりも、単純化による効能の方が大きい場合に、それは価値を発揮します。
逆に、元々が非常に単純な設計であれば、「複雑さを緩和する仕組み」そのものの複雑さが単に加わることになります。
小さなプログラムで逆に面倒に感じるのは、そういう問題もあるのかもしれません。


■多重継承について
実装を含む多重継承の好例は、C++標準ライブラリのstd::iostreamクラスです。
このクラスの設計に対する不満はあまり聞かないので、よい例に数えられているのだと思います。
(標準ライブラリの中にも「悪い設計」と評判のものがいくつかあるので要注意です!)
ただし、このような多重継承を【正しく】使うには、仮想継承や基底クラスメンバのusing、仮想基底クラスの初期化に関する制約、オブジェクトのメモリレイアウト、static_castやdynamic_castが裏でやっていることこと、等々、相当マニアックな事柄を完全に把握しなければなりません。
さらに、多重継承を【効果的に】使うには、多重継承による効果とそれがもたらす決して小さくない制約を比較して、それが一番いいと判断できる、非常に高い設計能力が必要です。
普通人には無理、ということでファイナルアンサーにしていいと思います。

ちなみに、実装を含まないクラスであれば、多重継承してもあまり問題を引き起こさないということがわかっています。
実装を含まないクラスとは、メンバ変数を持たず、メンバ関数の実装も持たない、つまり純粋仮想関数のみから成るクラスです。
JavaやC#ではそういうクラスを明確に区別するために、実装を含まないクラスを「interface」と名付け、「class」は実装を含むクラスだけを指すようにしました。
そして、classは一つしか継承したらダメけど、interfaceはいくつ継承(というか実装)してもいい、というルールにしたのです。
C++の自由かつ危険な部分にフタをして、安全設計にしているわけですね。


■インターフェイスとクラスの設計
>・インターフェイスにくっつくクラスはどれか?
>・そのクラス達に共通するものはないか?
>・共通したものを基本クラスとする
>という思考で設計していけば、OOP設計に近づくことが出来るのでしょうか。

その中で、「インターフェイス」を設計するところに一番重点を置くと、OOP設計に近づきそうな気がします。
それ以外の、インターフェイスにくっつくクラスを作ったり、共通部分を基本クラスにまとめたりするのは、あくまでインターフェイスの後ろでコソコソやればいい「実装」に過ぎません。
主役はインターフェイスです。

・【それ】は何ができるべきか? どんな情報を持つべきか?
・【それ】の機能や情報に、他のオブジェクトからどうやってアクセスするか?
・【それ】が持つ機能や特徴へのアクセス手段を、インターフェイスとしてまとめる。
・機能を実現し、特徴を保持するための実装を考える。

という思考の方が、よりOOPに近いと思います。

>簡単に対象、機能を切り替えられる
ようにするには、インターフェイスを「実装を持たないクラス」として作成し、実装はすべてその派生クラスに置くようにします。
クラスを使うときは、インターフェイスとなっている「実装を持たないクラス」だけにアクセスし、派生クラスは存在しないものとして扱います。
異なる実装を持つ新しい派生クラスを作って、もとの実装と入れ替えれば、クラスを使う側は一切変更しないままに「簡単に機能を切り替えられる」わけです。

ところで、「共通したものを基本クラスとする」というのは、#1さんが言う「実装の継承」なので、「悪い設計のサイン」に当たりそうです。
基本クラスにまとめるのではなく、別クラスにまとめてそれをメンバ変数として保持するというのが、一般に継承を使うよりもいい方法だといわれています。
class Base {};
class Class1 : public Base {};
class Class2 : public Base {};
ではなく、
class Common {};
class Class1 { private: Common m_common; };
class Class2 { private: Common m_common; };
とするわけです。
こうしたほうがいい理由は、『Effective C++』に詳しく書いてあります。

参考URL:http://d.hatena.ne.jp/sumim/20040525/p1

投稿日時 - 2009-08-25 01:38:31

ANo.15

#1 です。

> OOPを理解していると自負されている方は数多くいらっしゃることは
> 言うまでもなく、OOPについて説明している書籍はかなりあります。
> しかしながら、説明するキーワードは共通していても、
> 説明内容が各々で発散しすぎていると感じております。

これは仰るとおりです。
用語の揺れとしては、手前味噌ですが
http://d.hatena.ne.jp/bleis-tift/20090201/1233426011
の他にも、オブジェクト・クラス・インスタンスという用語にも人によって揺れがあります。

> (あくまで私の見解なのですが、もし、OOPを理解している人達が、
> ある同じ問題を各々でOOPでコーデングするれば、
> 限りなく一意に近いソースコードに成ると思いますが、
> どうなのでしょうか。
> なるのであれば、なぜ説明が収束しないのか不思議です。)

これはそれなりの規模で実験しないと分からないのですが、
似たようなグループはできるかもしれませんが、全てが同じようなものになることはないはずです。
なんというか、流派とでも言えばいいんでしょうか・・・
もしかすると、似たようなグループさえできず、
ちょっとずつ異なるものの連続になるかもしれませんが・・・

> コーディングする前に、必ずUMLで
> シーケンス図やクラス図を書いておりました。

スケッチとしての UML はいいのですが、
「UML を書く」という工程を入れてしまうのはどうかと思います。
これは、ER 図などにもいえることなのですが、
何らかの図を用いて設計するのではなく、思考を可視化してまとめる、または共通認識を得るために図に起こすのです。
ここを取り違えると、UML を書くことが設計だと勘違いしてしまいます。
なので UML が正しいかどうか、というのは実は全く問題ではありません。

少し厳しいことを言いますが、手続き型の方が考えやすい、と言うのは、
手続き型では「ただなんとなく」コーディングしてきただけなのではないでしょうか?
今まで行ってきた「手続き型言語での開発における設計」は、完全無欠に正しいものだったのですか?

> 初心者の私としては、多重継承しないように
> コーディングしていきます。

ある意味正しい方針、正しい制約かもしれません。
場数を踏む内にどういうことか分かってくると思いますし。

> インターフェイスの役割

これまた説明するのは難しいのですが、一言でいえば、
「何らかの抽象的側面を表すもの」
でしょうか。何言ってんだ、って感じですね(汗

簡単に実装を切り替えられるというのは、あくまでインターフェイスの特徴であって、役割ではありません。
・・・まぁあるコンテキストにおいて、ある interface が実装を切り替えることを目的としていることはあったりすのですが・・・
その場合でも切り替える実装の間には何らかの共通する抽象的側面があるはずです。

で、OOP のための設計の思考ですが・・・
あながち、間違いとは言い切れません。
共通性・可変性分析の、共通性のみに着目した考え方と言えるのではないでしょうか。
ですが、やはり可変性にも視点を向ける必要があると思います。


以下 #8 の人へ

クラス設計ですが、表現としては普通に使われてはいるのです。
ただ、その用語は本当に言いたいことを表しているの?と、個人的に疑問を持っているだけで・・・

で、ちょっと関係ないですが本について。
「Java デザインパターン徹底攻略」は自分も持っていたのですが、
問題も多かったように記憶しています。
もう手元にないのでどこに問題があったかは詳しく覚えていませんが、
一つ覚えているのが、マルチスレッドに対応した Singleton の項で、double checked locking イディオムを使用していたことです。
たしか 6 だか 5 だかで double checked locking イディオムが使えるように VM に変更が加えられたはずですが、
この本は確か 1.3 とか 1.4 時代に書かれています。
他にもいくつか問題があったように記憶していますので、あまり真に受けるべき本ではないかと・・・
Java に限定するなら、結城浩さんの「増補改訂版 Java 言語で学ぶデザインパターン入門」という本がおすすめです。
ただし、この本も 1.4 時代の本なので、ジェネリクスとか使ってないのがアレですが・・・

また、「デザインパターンとともに学ぶオブジェクト指向のこころ」、「アジャイルソフトウェア開発の奥義」という本もおすすめです。
これらの本を読んだ後、「パターン指向リファクタリング入門」という書籍もおすすめです。

次に、オブジェクト指向の 3 つの特徴について。
カプセル化、継承、ポリモーフィズムというのはよく言われることなのですが、
あくまでこれは「クラスベースのの OOPL」の特徴と言うべきものです。
メッセージパッシングに重きを置いた OOPL や、そこから派生したプロトタイプベースの OOPL には当てはまりません。
また、質問者さんへの回答でも述べたとおり、カプセル化という言葉は揺れが大きすぎ、
カプセル化と書いただけでは何も言っていないのとほとんど等しいというのが現状です。

最後ですが、回答中に挙げているサイトについて。
「デザインパターンを読み解く」については、Facade は Wrapper でもあるんじゃ?とか、いくつか「?」が付くだけですが、
「オブジェクト指向」は言いたいことがいくつもあります。

全部は挙げませんが、
open(door);

door.open();
という「書き方」を取り上げて、前者が手続き的で後者がオブジェクト指向的だという説明は間違っています。
対象を明示すると言う意味で door.open() の方が分かりやすい、という説明ならいいのですが、
それでも open(door) が手続き的かどうかは、open の実装によりますし、door.open() だったらオブジェクト指向的か、
と言われると、「それは違う」と答えます。
コンテキストを無視したコード片では、手続き的かオブジェクト指向的かという判断はできないと考えています。
書き方、形式の違いを例に出すのは、間違った OOP への第一歩です。OOP はそこまでミクロな視点のものではない。

メソッドの分類では、モジュールと言う考え方を無視しているため、違和感があります。
クラスの導入へのステップに飛躍がありすぎる、と言いましょうか・・・
また、クラスは「データにメソッドを付属させたもの」ではありませんし、
「メソッドの集まりに状態を保持させたもの」でもありません。
それはあくまで実装の話であって、それが直接メリットになるわけではないのです。
で、カプセル化については・・・もういいですね。

オブジェクト指向の 3 原則・・・ももういいですね。

それ以降は長くなるので省きますが、「機能とデータを併せ持ったモノ」という考え方では、よい設計は生まれません。
クラスをそのように取り違えているこの文書もまた、あまり参考にすべきではないかもしれません。

まぁそれを言ったら、この意見も「クラスは機能とデータを併せ持ったモノだ」という意見をもつ人から見れば、
あまり参考にすべきではないものでしょう。
要は「何を正しいとするか」なのでしょうけど、「クラス = データ + 手続き」という考え方からはよい設計が生まれないと言うことを
「デザインパターンとともに学ぶオブジェクト指向のこころ」により知ってしまったので、
自分の考え方はこの本が「基礎」になっています。

投稿日時 - 2009-08-24 10:18:20

#8です。ちょっとばかり追記です。

○  『クラス設計』について  ○

以前からデザインパターンの有用性については認識していたのですが、GoFのパターンだけでも23コもあるし、もっとデザインパターン自体の効率的な分類法などはないのかなあと考えていた時に、出会ったのが以下のサイトです。

「デザインパターンを読み解く」
http://www.happiese.com/system/dpattern.html

上記サイトでは、GoFのパターンを独自に分類されていまして、非常に感銘を受けました。(あぁ、こういった分類の仕方もあるものなのかと。)

恐らく、私がここのQ&Aサイト上で『クラス設計』という言葉を使い出したのも、このサイトに出会ってからだと思います。

あと、書籍でもいろいろ調べてみましたら、ありました。

標準プログラマーズ ライブラリシリーズ
Java デザインパターン徹底攻略
http://gihyo.jp/book/2002/4-7741-1579-7

上記書籍のp.17にある「オブジェクト指向言語とデザインパターン」の項ではちゃんと『クラス設計』という言葉の説明があって、クラス設計者という言葉も出てきたりします。

ただ、SmalltalkやRubyなど他の書籍などにはあまり馴染みが無いので、もしかしたら「オブジェクト指向」全般というよりも、あくまで「Java」の世界でよく使用される用語なのかなあと。この辺りは、他の諸先輩方の意見も伺ってみたいところ。

○  『クラス化』について  ○

こちらの方は、私の方でも再度読み返してみると、あまり好ましくない表現であったと思います。(よって、質問者さんもこの点については、気にしないでください。)

オブジェクト指向
http://www.happiese.com/system/objectorient.html

言わんとしていることは、上記サイト内での次の記述です。

「Cでは、メソッドが直に書かれていますが、Javaではメソッドが必ずクラスの中に書き込まれています。」

Cなどの関数と違って、Javaなどでは常にクラス内にてメソッドの宣言を行うため、必然的にオブジェクト指向の以下の3つの特徴が付いてくるということです。

・カプセル化
・継承
・ポリモーフィズム

投稿日時 - 2009-08-13 20:59:20

お礼

ご回答、ありがとうございます。
(返信が大変遅れてしまい、すみません。)

教えて頂いたページを拝見しました。

>「デザインパターンを読み解く」
​>http://www.happiese.com/system/dpattern.html
オブジェクト指向が全く分かっていなかった頃、
ご紹介頂いた「Java デザインパターン徹底攻略」を
読みました。

当然理解できなかったのですが、それでも、
何か似ているようなパターンがあるな、と素人ながら
思っていました。

現在、オブジェクト指向がやっと分かりかけてきている状態なので、
デザインパターンを理解するのはまだ先になりそうですが、
上記ページでは、それを分類分けされている点がとても
いいと思います。(頭が整理できると思います。)
将来、必ずこのページをまた訪れようと思います。

>オブジェクト指向
>http://www.happiese.com/system/objectorient.html
このページはいいです!
(後半は理解できていませんが、、、)
まさに手続き型とオブジェクト指向型の対比が紹介されていますね。
このページの著者がオブジェクト指向が有効であることを
述べていますが、必ずしも「オブジェクト指向が絶対にいい!」
なんて言っていません。
こういうことを書けるのは、手続き型、オブジェクト指向型両方を
きちんと理解されているからでしょうね。
(こちらのページも早速ブックマークに入れました。)

とても有効なページをご紹介していただき、ありがとうございました。

投稿日時 - 2009-12-01 17:11:22

ANo.13

> 本当にオブジェクト指向プログラミングっていいのでしょうか?

この手の話は議論が絶えないので違う観点からひとつだけ。


この手の質問を大学時代に先生に投げかけてみたことがあります。

先生の話によると、昔どのプログラム言語が優秀なのか調べる(?)ため、
言語毎にチームを作り、どの言語が一番早くシステム作れるか競う大会が行われたそうです。
当時オブジェクト指向は世の中には全く知られてなかったわけですが
オブジェクト指向を世に認知させるべく、smalltalkを作った研究者も参戦したそうです。

そしてその大会の第一問が、「次の要件を満たすシステムを作れ」という内容で
各チームがそれぞれの言語でシステムを作りました。

そして第二問で、「作成したシステムについて、次の通り仕様を変更せよ」と出題され、
このとき最も早く完了したのがsmalltalkを用いたチームだったそうです。

これがオブジェクト指向が「仕様変更に良い」とか「開発効率が良い」と言われる所以(噂!?)だそうなんですが
先生はこの話のあと、次のようにも付け足していました。

「オブジェクト指向の「オ」の字も登場していなかった時代に
 オブジェクト指向を考えた人たちが作るわけだから
 そんな優秀な人がやるならsmalltalkだろうがcだろうが優勝できるっしょ!」

まぁ、これは大学時代に先生から雑談半分で聞いた話で
あまり定かな情報ではないので参考程度にしておいてください。


しかし私もオブジェクト指向が良いというのは
話題性だけが一人歩きしている感じが否めないですね。

世の中のトレンドというのは
本当に正しいものだけがいつもまかり通っていると
必ずしも言えないときもあると思います。

Cをよく知っている人なら、Cで作成した方がキレイなコードを書けるでしょうし、
Javaをよく知っている人なら、Javaで作成した方がキレイなコードを書けると思います。

誰かも言っていますが、結局のところプログラマー次第となる問題かと思います。

(余談ですが、Linuxに入っているような一般的な(OSSなどの)ソフトはCで書かれているものが多いですしね!)

投稿日時 - 2009-08-10 13:19:24

補足

ご回答、ありがとうございます。
(返信が遅くてすみません。)

>Cをよく知っている人なら、Cで作成した方がキレイなコードを書けるでしょうし、
>Javaをよく知っている人なら、Javaで作成した方がキレイなコードを書けると思います。
>
>誰かも言っていますが、結局のところプログラマー次第となる問題かと思います。
>
>(余談ですが、Linuxに入っているような一般的な(OSSなどの)ソフトはCで書かれているものが多いですしね!)

全く、そのとおりだと思います。
#2さんの返信でも申し上げたように、
その言語がいくらオブジェクト指向言語でも、
それを扱う人間が使いこなせないと意味ないですからね。

現在、VC++でなく、C++の教本を読み始めて初めて
「オブジェクト指向言語ってこういう感じで組むんだ」
と分かり始めてきました。

ご回答、ありがとうございました。

投稿日時 - 2009-12-01 13:36:50

ANo.12

手続き型プログラミングより
オブジェクト指向プログラミングのほうが
統合開発環境でインテリセンスを有効利用できます。


クラスを単なる名前空間と関数の塊にするのは簡単なので
オブジェクト指向型で組んで失敗したと思ったことは無いです。
個人的には適切に構造化できていればそれはそれで良いと思いますし。

Javaのアプレットはページをリロードするだけで新しいインスタンスが作成されるので
マルチインスタンスを意識してコードを書いていないと大変なことになります。
最近のシステムでは手続き型で組んで失敗したと思うことは多いです。
純粋に手続き型で書かれたコードは使い回しが困難です。

投稿日時 - 2009-08-09 18:11:49

お礼

ご回答ありがとうございます。
(本当に遅い返信ですみません。)

お陰さまで、少しずつですが、オブジェクト指向プログラミングが
理解し始めてきました。
(今まで点であった知識が、線で結ばれ始めています。)

統合開発環境(?)は、VC++6とVC++2005(ExpressEdition)の
VisualStudioを使用しましたが、クラス化すると
関数ベースでコーディングしていたときよりも、
使いやすく感じます。

>純粋に手続き型で書かれたコードは使い回しが困難です。
今となると、困難だったのかなかなぁと思います。
(私の設計が悪いせいかもしれませんが、
 関数を作るのに、結構考え込みました。)
クラスにすると、コーディングの量は増えましたが、
簡単にメンバ関数を追加でき、そのクラス関数同士を
組み合わせて新クラス関数をつくったりしているので、
これが使いまわしが聞きやすいって事なのかなぁ、と
思っています。

ご助言、ありがとうございました。

投稿日時 - 2009-12-01 13:33:25

ANo.11

私も初心者で、Delphiなんですが、、、一応クラスやオブジェクト指向の事は分かります。

Delphiは基本的に関数でも、クラスでもOKです。
オブジェクト指向もサポートされています。

で、私がたどり着いた答えは、オブジェクト指向は便利だけど、面倒。
とくに、私のような日曜プログラマでは、開発するアプリの規模が小さく、1人で作っているので、あまり関係がないと決めました!(←これが大事。苦笑
関数はできるだけ、あとで使い回しができるように、私なりに汎用性を高く作っているつもりですし、困ったことはありません。
だって、オブジェクト指向が生まれる前は、みんな関数でやってたんでしょ?

ただ、SLGを作った時には、あー、クラス化、オブジェクト指向・・・というか、継承やポリモーフィズムって、そう言うことか!確かに、便利だわ!って実感しました。
これは関数ベースでは、ちょっと難しいかもと思いました。

ただ、頭が悪いせいか、未だに、普通のアプリを作る上では、関数ベースです。^^;
外部ライブラリー化したりはしますが、私は基本は関数です。
まぁ、とくに問題はないし、作りながら、先のレイアウトを考える悪いクセがあるので、関数ベースの方が楽だったりはします。

まぁ、ほぼ素人なので、お耳汚し程度で。

投稿日時 - 2009-07-31 23:13:13

お礼

ご回答、ありがとうごいます。
(本当に返信が遅くてすみません。)

>で、私がたどり着いた答えは、オブジェクト指向は便利だけど、面倒。
理解できていない私が言うのもつらいですが、
本当に面倒だと思います。
そして、私も手続き型で困った事は全くありません。

SLG(シミュレーションゲーム?)を作る際には、
手続き型だと厳しいのですか?
もし、SLGを作成しながらOOPを学べるような参考書が
ありましたら、教えて頂きたくお願いします。

投稿日時 - 2009-08-23 23:08:54

ANo.10

またまた#1です。

* 多重継承について

多重継承については言及していないのですが・・・
とりあえず、多重継承について。
多重継承は、悪だとは言い切れません。
ただし、多重継承を語る上では、「機能(実装)の継承」と「型の継承」の区別ができている必要があります。
まずはこの2つの継承について理解する必要があります。

「実装の継承」とは、その名の通り、親クラスから子クラスへと実装を継承(コピー)することです。
この継承の形は、「差分プログラミング」とオブジェクト指向黎明期にはもてはやされましたが、
現在ではこの形での継承は積極的に利用するべきものではない、と言うのが一般的な認識です。

もう一方の「型の継承」は、イメージが掴みにくいかもしれません。
要は、共通のインターフェイスをくくり出すための仕組み、と言えばいいでしょうか。
「特徴」と言い換えてもいいかもしれません。
ここで言う型には実装が含まれないため、差分プログラミングにはなりません。
実装は子クラスで提供する必要が出てきます。

そして多重継承ですが、多重継承にも「実装の多重継承」と「型の多重継承」があります。
JavaやC#といった言語では、「型の多重継承」は可能ですが、「実装の多重継承」が禁止されています。
C++では、そもそも「実装の継承」も「型の継承」もシンタックス上の区別が希薄なため、どちらも可能となっています。

多重継承が即悪い設計、と言うわけではなく、「実装の継承」が悪い設計のサインとなっているため、
「実装の多重継承」も悪い設計のサインとなりますよね?
また、単一継承よりも多重継承の方が複雑であるため、「実装の多重継承」はより悪い設計である可能性が高いと言えます。

以上のことから、多重継承でも正しいOOPというのが成立する可能性があることはわかっていただけるかと思います。
ただし、そう言ったケースは稀な上、下手をすると簡単に悪い設計になってしまうため、
C++よりも新しい言語では(実装の)多重継承ができなくなっているものが多いのです。

また、多重継承の特殊な形として、Mix-inというものもあるのですが、それはまた別の話・・・

*OOPも非OOPでも面倒なのは同じなら、慣れている非OOPでもいいのかな、とも思ってしまいます

面倒、という観点から見ると、どちらも同じなのはわかっていただけたようで。
ただし、利点はそれだけではありません。
ポリモーフィズム(多態、ポリモフィズム)を使うことで、可変性(差違)をクラスに閉じ込めることができます。
詳しくは、オブジェクト指向のこころをどうぞ。

*クラス設計やクラス化という言葉について

ちょっと横道にそれて、クラス設計やクラス化という言葉について。
クラスベースのオブジェクト指向プログラミング言語なのだから、こういう言葉が出てくるのもある程度は仕方ないのですが・・・
少し、誤解を与える言葉だと考えています。
静的型付けのOOPLのほとんどの言語でinterfaceと言うものがありますよね?
C++には構文上はないですが、意味的には同じものを作ることができます(し、Javaを触ったことがあるようなので問題ないでしょう)。
本来ならば、こちら、interfaceを中心に考えるべきだと思うのです。
実際のクラスは、あとから出てくる(TDDで組むと、classからinterfaceをくくり出すため、逆ですが・・・それはまた別の話)。
ならば、クラス設計ではなく、インターフェイス設計と呼ぶか、せめてインターフェイス・クラス設計と呼ぶべきではないでしょうか。

クラス化についての違和感は更に強いものがあります。
(C++やJavaといった、静的型付けのクラスベースの)オブジェクト指向プログラミングでは、
複数のインターフェイス、複数のクラスが組み合わさって意味のある単位となっていることが普通です。
1つのクラスで完結するものの方が稀です。
ですが、クラス化という表現は、あくまで何らかのモノを1つのクラスへと落とし込むような、そんなニュアンスが感じられてしまうのです。

ちょっと結局何が言いたかったのか分かりにくくなっているような気もするのですが・・・
また、何かあれば書いていただければ反応します。

投稿日時 - 2009-07-29 22:12:07

お礼

ご回答、ありがとうございます。
(本当に、返信遅くてすみません)

多重継承の件、分かりました。
(といっても70~80%くらいですが、、、
 あとは実践で理解していけると思います。)
初心者の私としては、多重継承しないように
コーディングしていきます。

>クラス設計ではなく、インターフェイス設計と呼ぶか、
>せめてインターフェイス・クラス設計と呼ぶべきではないでしょうか。
あぁ、なるほど、と思いました。
OOPが理解できないないので、インターフェイスの役割も正確に
理解はしておりませんが、簡単に対象(?)、機能(?)を切り替えられる
というふうに認識しております。
そうすると、
・インターフェイスにくっつくクラスはどれか?
・そのクラス達に共通するものはないか?
・共通したものを基本クラスとする
という思考で設計していけば、OOP設計に近づくことが出来るの
でしょうか。

もし、私の認識が間違っているようならば、ご指摘いただけると幸いです。

投稿日時 - 2009-08-23 22:20:37

ANo.9

個人的な意見です、参考程度にしてください。

手続き型、オブジェクト指向型 での大きな違いは
0から開発をすることを考えると長期なプラットフォームでの開発では
オブジェクト指向で設計してプログラムを簡略化、短期なプラットフォームでは手続き型みたなに感じになります。
開発規模にもよりますが、設計期間がオブジェクト指向型のほうが
時間がかかります。この段階で失敗すると、オブジェクト指向にした意味がない作りになってしまいます。
デバッグを考慮すると、複数の人が同じようなコーディングをさせることで見やすくすることを考えるとオブジェクト指向になります。クラス化により書き方を自由にさせないという利点があります。C,C++で考えると分かりやすいと思います。

クラス=オブジェクト
C,C++の対比で言えば、モジュール(1 File)=クラス

オブジェクトしてどのようなことをするかを考えるかです。
Windowsプログラムで考えた場合、GUIで考えると
ボタン、テキストボックス などのように管理対象をどのようにするかを考えると分かりやすいと思います。

投稿日時 - 2009-07-29 11:38:12

お礼

ご回答ありがとうございます。
(だいぶ返信遅れてしまい、すみません。)

やはりOOPで設計する方が、時間がかかるのですか、、、
確かに、以前Javaを勉強してコーディングしていたときも、
コーディングする前に、必ずUMLで
シーケンス図やクラス図を書いておりました。
(不慣れな原因もありますが、)
この手間があるから、とても作業が遅かったことを覚えています。
しかも、そのUMLが正しいかどうか判断がつきませんでした。

そう考えると、手続き型の方が
考えやすく、簡単にコーディングできると思います。
でも、これではずっとOOPは理解できないままなのでしょうね、、、

投稿日時 - 2009-08-23 22:00:52

JavaがメインでしてMFCや.NET関連は全くの無知の者ですが、タイトルが「OOP」ということもあり、少しだけ参戦。

デザインパターンによるJava実践プログラミング
http://ascii.asciimw.jp/books/books/detail/4-7561-4155-2.shtml

上記の書籍は初版発行が2002年9月21日でして、今となってはかなり古かったりもするのですが(最近の若い人は知らないかな?)、GoFの前にちゃんとAlexander教授(建築学)の紹介がしてあったりとか、各パターンの説明にも「GoFフォーム」を利用し、随所にクラス図やシーケンス図が出てきたりなど、今でもそれなりに良書といえるのではないか、と思っています。その中から、少しばかり紹介。

上記書籍の「はじめに」の所で、『ソフトウェアの抽象化と再利用』というのがあり、その中でp.26の「表1 再利用と抽象化の方法」内で、再利用の種類として以下の10項目を上げています。

・断片的な再利用
・データ構造の再利用
・関数の再利用
・テンプレートの再利用
・アルゴリズムの再利用
・クラス(インターフェイス、ポリモーフィズム、抽象クラス)
・コードライブラリ
・API
・コンポーネント
・デザインパターン

一番上の「断片的な再利用」というのは、CaP(カットアンドペースト)のことでして省くとしても、やはり『抽象化』についてはそれぞれ異なるものの、『再利用性』と『汎用性』については下の項目にいくほど、高くなっていきます。デザインパターンの場合は、どちらも「非常に高い」です。

確かに、デザインパターンを適用さえすれば良い、というわけではありませんが、必然的にクラス設計をしっかりしていけばそのような近い形になっていきますし、クラス単位で考えていくと慣れてくれば「可読性」も向上しますし、修正の際にも、あるクラスだけで他のクラスには影響しないということになり、高い「保守性」も望めますね。

手続き型からOOPへの飛躍の一つに、「関数化とクラス化の違いをきちんと理解しているか?」というのが挙げられるかと思います。質問者さんもまだ2,3冊程度しか読まれていない状態かもしれませんが、もう一歩踏み込んで4,5冊目辺りになってくると、知っている知識がかなり増え、未知の部分のみじっくりと読み進めていけばいいのでかなりスピードもアップしますし、その頃にはより「オブジェクト指向」の理解が深まっていることと思います。頑張って下さい。

投稿日時 - 2009-07-27 01:56:51

お礼

ご回答ありがとうございます。
(返信遅れてすみません。)

>手続き型からOOPへの飛躍の一つに、「関数化とクラス化の違いを
>きちんと理解しているか?」というのが挙げられるかと思います。
ご指摘のとおり、恥ずかしながらこの点は十分に理解していません。
(だから、「オブジェクト指向言語っていいの?」って
 疑問が私にあるのだと思います。)

ご紹介いただいた「デザインパターンによるJava実践プログラミング」
を今度書店に行って見てみようと思います。
(表紙の印象では、とても難しいそうに感じますが、、、)
とにかく、諦めずにその手の書籍を読んでみようと思います。

投稿日時 - 2009-07-28 23:19:45

ANo.7

#1 です。

#4 の回答はちょっとまずいかな・・・と思ったのでちょっと苦言を。

> C++言語はオブジェクト指向を熟知している人がオブジェクト指向になるように作ればオブジェクト指向プログラミングが可能な言語であって、必ずしもオブジェクト指向向きの言語ではありません。

それは、C++ に限らず、どんな言語にも言えることです。

> C言語からの継承もあってオブジェクトでは無い物を書けますし、MFCを使用する場合にはオブジェクトに収まらない領域にアクセスする必要が出てしまったりします。

「オブジェクト」という用語を何に対して使用しているのでしょうか?
「オブジェクトに収まらない領域」という言葉が何を言っているのか、いまいちわかりません。

> オブジェクト指向の意義と利点の理解には「オブジェクト指向でなぜ作るのか」が分かりやすくてお勧めです。

この本は、「間違ったオブジェクト指向」の本なので全くおすすめできません。
あまりにも「Java のオブジェクト指向」に偏りすぎているのも問題です。

オブジェクト指向でなぜ作るのか を買ってみました
http://d.hatena.ne.jp/minekoa/20080803/1217795027

> C++の言語使用の為でJavaでは呼べるように作ればインスタンスを作ら無くても呼べる。

C++ にもクラスメソッド (静的メンバ関数) はありますので、これは間違いです。

> C/C++ではメモリー管理がプログラマ責任になっているためです。
> インスタンスを配列に置き換えても同じことが言えます。
> オブジェクト指向だから…ではなくC++言語だから…です。

RAII を Java では実現できませんが、C++ では可能です。
C++ ではメモリ管理はプログラマが行うこともできますが、ふつうの C++ プログラマならスマートポインタを使います。
更に、Java など他の言語ではメモリ以外のリソース (入出力ストリームなど) の管理がプログラマ責任になっています。
しかし、C++ ではすべて言語に任せることができます。
オブジェクト指向には関係ないですが、C++ を見くびりすぎではないですか?

自分も Java は好きですが、Java の世界しか知らない人の意見に思えました。

投稿日時 - 2009-07-26 15:16:35

お礼

ご回答、ありがとうございます。
(返信が大変遅れてすみません。)
再度のご教授、本当にありがとうございます。

>> C++言語はオブジェクト指向を熟知している人がオブジェクト指向に
>>なるように作ればオブジェクト指向プログラミングが可能な言語で
>>あって、必ずしもオブジェクト指向向きの言語ではありません。
>それは、C++ に限らず、どんな言語にも言えることです。
確かに、そうかもしれません。
現在、OOPでコーディングできるプログラミング言語は
増えてきましたが、その中でもRubyはOOPでスクリプト言語だから
とても開発効率がよい、という記事をどこかでみて
Rubyを使用しました。
しかしながら、OOPが理解できていない私には、
結局Rubyでも手続き型のように組んでしまうのです、、、

また、#4さんがお薦めしていただいた本に対する
ご意見、ありがとうございます。
一方、OOPが理解していない私に
良心的に答えて頂いた#4さんにも感謝をしております。
しかしながら、OOPの理解に混乱する原因はここにあると思います。
OOPを理解していると自負されている方は数多くいらっしゃることは
言うまでもなく、OOPについて説明している書籍はかなりあります。
しかしながら、説明するキーワードは共通していても、
説明内容が各々で発散しすぎていると感じております。
(あくまで私の見解なのですが、もし、OOPを理解している人達が、
 ある同じ問題を各々でOOPでコーデングするれば、
 限りなく一意に近いソースコードに成ると思いますが、
 どうなのでしょうか。
 なるのであれば、なぜ説明が収束しないのか不思議です。)

OOPを理解していない私には、どの本が良書で悪書か判断できません。
やはり、良書と呼ばれるものをひたすら読んで、自分に理解できる
レベルか否か判断して、駄目なら、他の良書と呼ばれるものを
あさるしかなさそうです。

やはり、OOPを理解する道は険しそうです。

投稿日時 - 2009-08-17 02:19:23

ANo.6

個人的な意見になりますが、すべては作成する人次第です。
どんなに目的に適している言語を使用していても、分かりやすく作れないひとはたくさんいます。その言語の理解力にかかっているということになります。

大雑把な説明でいうと(かなり大雑把ですけど)
Cの場合見やすくするために機能別に関数にしたりしていますが
C++で行う場合クラスにすることでまとめます。

Cの場合、関数間で共有する変数は外部変数として定義しなければなりませんが、C++の場合、クラスにすることでクラス内の関数のみ参照出来るようにできます。

投稿日時 - 2009-07-26 01:36:59

お礼

ご回答、ありがとうございます。
(返信遅れてすみません。)

>個人的な意見になりますが、すべては作成する人次第です。
初心者の私が言うのも苦しいですが、本当にそう思います。

現在、先人が残したMFCのソースを修正していますが、
OOP、非OOPを語る以前の問題で、1つのクラスが500行以上あったり
3重、4重ループがあったり、深い階層のif節があったりします。
(そして、コメントはほとんどなく、何をしているか理解するのに
 本当に苦労しています。)

アドバイス頂いたその大雑把な説明が私には
とても理解しやすい、というよりも、イメージしやすいです。
これからの自分で修正するOOPソースには、
今まで関数でまとめていた事を
クラスとしてまとめようと思います。
(OOP設計の方向がつかめたような感じです。)
しかしながら、適切なクラス設計は大変なんでしょうけど、、、

投稿日時 - 2009-07-29 02:28:08

ANo.5

> ・インスタンスをつくってから、関数を呼ぶのが面倒な気がする。
>  (手続き型なら関数呼び出しのみで済みます。)

解説書はインスタンスを1つしか作っていないから、そのメリットを受けられないんだと思います。

構造体型の変数を2つ3つ作るのと似たようなものではあるんですけど、
どの変数(オブジェクト)に対して処理をするか、というのを、
手続き型ではいちいち引数で指定しないと行けないですからね。
OOPでは「自分自身」が対象ですから、指定する必要はありません。

また、すでに出ていますが、関数を呼び出すときに引数を減らせるメリットが出ます。
OOPにすると、そのオブジェクト内でグローバルに使える変数(プロパティ)がありますから、
それを使っている限り引数を省略できます。
(メソッドの数が増えたりしますが(^^;)

> ・継承されすぎると、基本クラスまで追うのが一苦労。
> ・ソースを追いにくい(慣れの問題なのでしょうか、、、)

ソースを追うどうかは、既存(完成した)ライブラリのソースを追わないのと同じだと思います。

投稿日時 - 2009-07-25 21:05:59

お礼

ご回答ありがとうございます。
(返信が大変遅れてしまい、申し訳ございません。)

>手続き型ではいちいち引数で指定しないと行けないですからね。
>OOPでは「自分自身」が対象ですから、指定する必要はありません。
>また、すでに出ていますが、関数を呼び出すときに引数を減らせるメリットが出ます。
そうですね。手続き型ですと、引数が膨大になる可能性がありますね。
(良いかどうかわかりませんが、引数を減らすように、いつも中間
ファイルを作成していました。)
OOPですと、オブジェクト内でオブジェクト自身が持つ変数ならば、
オブジェクト内に限り、グローバル変数のようにどこでも呼べますよね。
(この認識は、OOPを理解する上で正しいのでしょうか?)

>ソースを追うどうかは、既存(完成した)ライブラリのソースを
>追わないのと同じだと思います。
ご指摘のとおり、ライブラリのソースは追いません。
というよりも、追った事がございません。
その理由は、MSDNを始めとするサイトで、
ライブラリ関数の説明、使用例が紹介されているからだと思います。
しかしながら、現在私の置かれている状況は、簡素な仕様書、
及び、コメントの少ないソースコードのみです。
そうなると、何をしているのかソースを追う事になるので、
今はそれがとても辛いです。
(泣き言になってしまい、すみません。)

アドバイスありがとうございました。

投稿日時 - 2009-08-17 00:29:48

ANo.4

C++言語はオブジェクト指向を熟知している人がオブジェクト指向になるように作ればオブジェクト指向プログラミングが可能な言語であって、必ずしもオブジェクト指向向きの言語ではありません。
C言語からの継承もあってオブジェクトでは無い物を書けますし、MFCを使用する場合にはオブジェクトに収まらない領域にアクセスする必要が出てしまったりします。

その点ではJavaの方がオブジェクト指向の利点を感じやすいです。

オブジェクト指向は構造化プログラミングの欠点を補うために発明されたと思っています。
で、構造化プログラミングの欠点は小規模、少人数、短期間の開発では感じにくい(というか、ほとんど感じない)のです。
大規模、大人数、長期間の開発になったときに、安全性・確実性を担保できるだけでも物凄いメリットなのですけどね。

オブジェクト指向の意義と利点の理解には「オブジェクト指向でなぜ作るのか」が分かりやすくてお勧めです。

その他、言語仕様やツールの問題でオブジェクト指向の問題では無い点もあります。
>・継承されすぎると、基本クラスまで追うのが一苦労。
 そもそも基本クラスを追う必要が(本来なら)無い。

>・インスタンスをつくってから、関数を呼ぶのが面倒な気がする。
 C++の言語使用の為でJavaでは呼べるように作ればインスタンスを作ら無くても呼べる。

>・インスタンスをdeleteし忘れて、メモリを圧迫する危険がある。
 C/C++ではメモリー管理がプログラマ責任になっているためです。
 インスタンスを配列に置き換えても同じことが言えます。
 オブジェクト指向だから…ではなくC++言語だから…です。

>・ソースを追いにくい(慣れの問題なのでしょうか、、、)
 VC++2005/2008やEclipse、NetBeansIDEなどのクラスエクスプローラーが充実しているIDEだと楽に追えます。
 互換性の都合でVC++6と2005を併用していますが、2005に慣れた今ではVC++6はあまり使いたく無いです。
 (VC++6だとソース追っかけるのが面倒なので)

投稿日時 - 2009-07-25 03:26:27

お礼

ご回答ありがとうございます。
(大変遅い返答になり申し訳ございません。)

>C言語からの継承もあってオブジェクトでは無い物を書けますし、
>MFCを使用する場合にはオブジェクトに収まらない領域にアクセスする
>必要が出てしまったりします。
>その点ではJavaの方がオブジェクト指向の利点を感じやすいです。
私の場合、MFCもJavaも熟知しておりませんので、恐縮ですが、
オブジェクトに収まらない領域にアクセスする領域とは
どのような事でしょうか。
また、Javaを使用しましたが、オブジェクト指向を理解していなかった
ので、手続き型のようにコードを書いてしまい、結局その利点を
感じることは出来ませんでした。

>大規模、大人数、長期間の開発になったときに、
>安全性・確実性を担保できるだけでも物凄いメリットなのですけどね。
このことは、私の読んだ参考書に同じようなことが書かれておりました。
私にはそのような大規模なものに取り組んだことがない為、
実感できていないのかな、と思っております。

投稿日時 - 2009-08-17 00:06:10

ANo.3

ちなみに、

オブジェクト指向⊂手続き型

ですよね。一般的には。
対立概念ではないと思います。

>個人的には、手続き型プログラミングの方が好きです。

それならそれで良いのでは?
他の人が「いい」と言うから、と言う理由で盲信しなきゃいけない、って事は無い筈ですけれども。本来なら、ですね。
まあ、会社で「こう言う形式でこの言語で書いてくれ」と言うガイドラインがあるなら別ですが、個人的レベルでは

「××と言う形式を好きにならなきゃいけない」

って事は無いでしょう。
懐疑的で良いのではないですか?

>「手続き型は~~で大変だけど、オブジェクト指向ならこんなにすばらしい」
>というような対比的に具体例を挙げて説明されている
>書籍、サイトの紹介、または、よい助言を頂けませんでしょうか。

へそ曲がりなんで(笑)、逆を挙げてみましょうか(笑)。
実はyuki7091さんの「感覚」の方が正しいのかもしれませんよ(笑)。

Bjarne Stroustrup Interview about C++ :
http://hp.vector.co.jp/authors/VA000092/jokes/strup.html

これは冗談ですが、自虐的ジョークに思えます。と言うのも「その手の批判がある」ってのは事実だから、でしょう。
他にオブジェクト指向に付いては

バベル案内:
http://www.aoky.net/articles/steve_yegge/tour_de_babel.htm

いいアジャイルと悪いアジャイル:
http://www.aoky.net/articles/steve_yegge/good_agile_bad_agile.htm

なぜArcはとりたててオブジェクト指向でないのか:
http://practical-scheme.net/trans/noop-j.html

Rees Re: OO:
http://practical-scheme.net/trans/reesoo-j.html

辺りに色々書かれているのでご覧ください。

投稿日時 - 2009-07-24 22:49:12

お礼

ご回答ありがとうございます。
(返信遅れてすみません。)

Bjarne Stroustrup Interview about C++ :
http://hp.vector.co.jp/authors/VA000092/jokes/strup.html
教えていただいた上記の記事から以下を抜粋します。
「プロジェクトの設計と、C++プロジェクトの設計の違いに気付いた
ことはありませんか。 C++プロジェクトの設計段階にかかる時間は、
3倍です。 継承すべきもの、すべきでないものを正確に決めるためです。
それでも、判断を間違えます。 」

抜粋した記事のように、(慣れもありますが)
私には、オブジェクト指向型の方が設計には時間がかかるとは
思います。
(使う分には便利でいいのですが、、、)

非OOP設計だと大規模なソースを書くには好ましくない、
とどこかの記事で見ましたが、質の悪いOOPソースの
方がよっぽどタチが悪いような気がします。
(漠然とした言い方でしか表現できなくてすみません。)

間違ったOOP設計をしない為に、UMLも昔勉強しましたが
OOPが理解不十分なので、UMLも未消化に終わっています。
やはり、OOPを理解する為には、デザインパターンやUMLも
必要となり、私にはかなりOOPの理解する敷居は高いと感じます。

ちょっと脱線気味になりましたが、悔しいので
今はOOPがまだ完全に理解できなくても
理解できるように勉強を続けていきたいと思います。

投稿日時 - 2009-07-29 02:04:38

ANo.2

うーん。大前提となるところに大きな問題があると思うんだが。

MFCは、「オブジェクト指向」じゃないだろう(笑)、という突っ込みは。まぁ脇に置いて。MFCをもって「オブジェクト指向は難しい」といわれてもなぁ……。そうじゃなくて、ただ単に「MFCが難しい」というだけと思うんだが。

MFCは、Cからのユーザーの取り込みを重視していて、旧来のWindows APIに毛が生えた程度のラッピングクラスとリソースを組み合わせてなんとかごまかしている。オブジェクト指向のフレームワークの中で、「もっともオブジェクト指向的でないもの」だろうと思う。MFCの難しさの大半は、「MFCだから」であって、「オブジェクト指向だから」ではないだろう。

どうも、見たところ、C++をもって「オブジェクト指向は……」といっていると思うんだが、C++は、オブジェクト指向言語だろうか? 「オブジェクト指向にも対応した言語」であって、これをもってオブジェクト指向と思われてしまうと、どうなんだろう。

もう少し、他の言語も見てみるといいと思うんだが。オブジェクト指向というものを深く知りたいなら、まずC++から離れなさい。と助言するしかないだろう。せめて、JavaかC#か、あるいはRubyあたりを勉強すれば、がらりと印象は変わると思うんだが。

>「手続き型は~~で大変だけど、オブジェクト指向ならこんなにすばらしい」

うーん。例えばだが、シンプルなウインドウが1枚あって、マウスでドラッグしたりリサイズしたりでき、クローズボックスをクリックすると終了する、そんなプログラムを作るとしよう。構造化言語(なんでもいい)で、どのぐらいのコーディングが必要だろうか。例えばJavaなら、まぁ実質5行も書けば完成する。どっちが楽だろう?

投稿日時 - 2009-07-24 22:36:49

お礼

ご回答、ありがとうございます。
(返信遅れてすみません。)

>MFCは、「オブジェクト指向」じゃないだろう(笑)、
>という突っ込みはまぁ脇に置いて。
技術力が低くてすみません。
突っ込まれても、「自分は変な事いっているの?」っていう状態です。
私の認識ではMFCはAPIとC++が合体したような言語だと思っていますが
間違いなのでしょうか。

>JavaかC#か、あるいはRubyあたりを勉強すれば、
>がらりと印象は変わると思うんだが。
私自身、JavaもRubyも勉強程度には経験はございます。
自作のJavaやRubyのソースを見ると気持ち悪いのです。
原因は、せっかくのオブジェクト指向言語なのに手続き型っぽく
自分ソースが組まれているからです。
だから、言語ではなく、やはりソースの組み方が重要だと思いますが
如何でしょうか。

せっかく、回答頂いているにも関わらず、
その回答に対して更なるたくさんの質問をしてしまった
無礼をお許し下さい。

投稿日時 - 2009-07-29 00:12:23

ANo.1

C++ で OOP をすることの是非はこの際置いておくとして、まず気になった点から。

>・継承されすぎると、基本クラスまで追うのが一苦労。
これは、「間違った」オブジェクト指向プログラミングが原因である場合が多いです。
オブジェクト指向に「間違ってる」とか「間違ってない」とかあるの?というある種危険な方向に進んでしまいがちな話題ですが、あえてこの表現を使いました。

>・インスタンスをつくってから、関数を呼ぶのが面倒な気がする。
非 OOPL の場合、関数の引数が増えがちで、見にくくなりやすいという問題がありますよね?
また、構造体にまとめたとしても、その構造体をつくる必要があります。
これ、インスタンスをつくるのとどちらが面倒ですか?同じだと思います。

>・インスタンスをdeleteし忘れて、メモリを圧迫する危険がある。
OOP の話ではなく、C++ の話になってしまうのですが、RAII というイディオムが C++ にはあります。
このイディオムを使用した「スマートポインタ」というクラスを使用することで、delete し忘れが防げます。
また、構造化プログラムでもメモリを動的確保・解放することはよくありますよね?malloc とか free とか。
他にも、FILE 構造体を操作する fopen とか fclose とか。
こういったものが、RAII イディオムを使用することで、確実に解放忘れがなくなります。
OOP の利点ではないですが、クラス (とテンプレート) を使うことの大きな利点になるのではないでしょうか。

で、書籍ですが、OOP 自体なら「デザインパターンとともに学ぶオブジェクト指向のこころ」という本がおすすめです。
そして、その後に「アジャイルソフトウェア開発の奥義」や「Java 言語で学ぶデザインパターン入門」、「パターン指向リファクタリング入門」に進むのがいいと思います。

と、ここまで書いたのですが、C++ という言語は OOP だけでなく、様々なパラダイムをサポートするマルチパラダイム言語です。
個人的には、OOP だけに偏った学び方はあまりよくないと考えています。
ですので、C++ In Depth シリーズの本をおすすめします。
Exceptional C++ や、Modern C++ Design などです。
また、テンプレートに関しては、C++ テンプレートテクニックという日本人が書いた本がありますので、そちらもおすすめしておきます。

で、手続き型で組んで失敗した例、ですか・・・
自分自身、初めてまともに触った言語が Java なので、手続き型と意識して何かを組んだことがないのですよね・・・
オブジェクト指向で組んで失敗した例ならいくつもあります。でもそれは手続き型にすればよかった、ではなく、オブジェクト指向に対する理解が浅かった、と考えています。
例えば、「問題領域から名詞を抽出し、クラスの候補とし、動詞を抽出し、メソッドの候補とする」という設計方法(?)があるのですが、これは実はあまりよろしくない。
詳しくは「オブジェクト指向のこころ」を読んでいただくとして、こういった「間違った」説明が溢れているのがオブジェクト指向の欠点、ですかね。

以上です。

投稿日時 - 2009-07-24 22:16:08

お礼

ご回答ありがとうございます。
(返信遅れてすみません。)

・多重継承について
 ご指摘して頂いたように、多重継承は間違ったOOPということは
 どこかで聞いた覚えがあります。その間違ったOOPをしないために
 Javaは多重継承ができなかった、と記憶しています。
 (うろ覚えですみません)
 しかしながら、多重継承でも正しいOOPというものがあるのでしょうか。
 正しいOOPがあるからC++では多重継承を許可しているのでしょうか。
 また、何を持って正しい、正しくないかが分かっていないので、
 どんどん「分からないスパイラル」に陥ってしまいそうです、、、

・インスタンスをつくってから、関数を呼ぶのが面倒
>非 OOPL の場合、関数の引数が増えがちで、
>見にくくなりやすいという問題がありますよね?
ご指摘頂いて、そういえばそうだなぁ、と思いました。
だからといって、OOPも非OOPでも面倒なのは同じなら、
慣れている非OOPでもいいのかな、とも思ってしまいます。
(既存のソースがOOPで組んであるなら、そのソース修正の際は
 不慣れでもOOPで組もうと思います。)

・インスタンスをdeleteし忘れて、メモリを圧迫する危険がある。
RAII、スマートポインタというのを初めて知りました。
(この時点で、私の技術レベルを推し量られてしまいますね。)
とても便利そうなので、この2つを早く使えるようにしようと思います!

ご紹介していただいた書籍の
「デザインパターンとともに学ぶオブジェクト指向のこころ」
を今度書店で見てみようと思います。
この本で何とかOOPの有用性が分かって
使いこなせればいいな、と思います。

この度は、長文にわたる回答をして頂き、本当にありがとうございました。

投稿日時 - 2009-07-28 23:57:18

あなたにオススメの質問