
いつもお世話になっております。
VC++初心者です。
現在、VC++6.0、MFCのソース修正で四苦八苦しています。
(コーディングするよりも。ソースを追うので苦労してます。)
(初心者の私が言うのも難ですが、オブジェクト指向云々言う前に
ソースのif文節が異常に長かったり、3重以上ループが出てくると
とても嫌になります、、、)
一般的(?)に、プログラミングは
手続き型プログラミングよりオブジェクト指向プログラミングが
開発効率がよい、と重宝されているようですが、
どうも納得できていません。
(その手の書籍を2,3冊読みましたが消化不良に終わっています。)
個人的には、手続き型プログラミングの方が好きです。
というのも、慣れているからかもしれませんが、
ソースが追いやすいし、見やすいと思います。
逆にオブジェクト指向プログラミングでは、
・継承されすぎると、基本クラスまで追うのが一苦労。
・インスタンスをつくってから、関数を呼ぶのが面倒な気がする。
(手続き型なら関数呼び出しのみで済みます。)
・インスタンスをdeleteし忘れて、メモリを圧迫する危険がある。
(ガーベージコレクションというものもあるようですが、
どこで何を消しているか不安です。)
・ソースを追いにくい(慣れの問題なのでしょうか、、、)
そこでですが、
「手続き型は~~で大変だけど、オブジェクト指向ならこんなにすばらしい」
というような対比的に具体例を挙げて説明されている
書籍、サイトの紹介、または、よい助言を頂けませんでしょうか。
また、上記に伴い、
・手続き型で組んで失敗した例(オブジェクト指向型にすれば良かった例)
・オブジェクト指向型で組んで失敗した例(手続き型にすれば良かった例)
も宜しければ教えて頂きたく、お願いします。
(成功例のみよりも、失敗からの成功例を教えて頂けると嬉しいです。)
長くなりましたが、宜しければご教授下さい。
A 回答 (17件中1~10件)
- 最新から表示
- 回答順に表示
No.17
- 回答日時:
#8です。
まだ、締め切ってなかったんですね。(私的なサイト・ブログを持たない者にとっては、大変有難いもので。)まず初めに、『本の紹介、リンク』について。
以前にも、Linuxカテなどで他の回答者さんからいろいろと同様のご指摘を受けたのですが、基本的に私が紹介している書籍というのは、自分が所有している物でも何でもなく、中には大型書店でちらっと立ち読みした物なども含まれていて、あくまで「どの本がいいのか迷っている方には、まず最初に立ち読みするための目安としてください。」的なニュアンスがあります。
よって、本当は別にもっといい良書があるのだけれど、それは他の方が既に紹介されているので私の方では割愛し、2冊目、3冊目としてはいいのではないかという感じで、別のをわざと紹介していたりします。
パターン本の良書といったら、やはり結城さんの本ですね。(但し、Java以外の方々にとっては、若干違和感があるのかもしれませんが。)
「増補改訂版Java言語で学ぶデザインパターン入門」
http://www.sbcr.jp/books/products/detail.asp?sku …
「デザインパターンとともに学ぶオブジェクト指向のこころ」については、私自身、初めて知りました。また、時間的な余裕が出来次第、こちらの方も読み進めていこうかな、と。
>やはり、OOPを理解する為には、デザインパターンやUMLも
>必要となり、私にはかなりOOPの理解する敷居は高いと感じます。
現時点で未だ紹介されていない書籍の一つに、「専門誌」が挙げられます。中には、重要な技術をコンパクトにまとめている物もいくつかあるので、そういったのも利用されたらよろしいかと。
「UML PRESS Vol.1」
http://gihyo.jp/magazine/umlpress/archive/2001/v …
上記の専門誌の「特集2 身近な例でGoF 総ざらい&サーバサイドJava ぼくにもわかるデザインパターン 」では、主要なGoFパターンについて、1パターンをB5版1ページずつで紹介していて、各クラス図の掲載もあり、ざっと各パターンを把握するにはとても便利な書籍です。結城さんの本みたいに、具体的なソースについての記載は一切ありませんが、言い換えると言語を限定していないということなので、それはそれでいいことなのかなと。
ただ問題は、発売からかれこれ8年以上経つということもあり、Amazonでも中古でしか手に入りません。
ちなみに、以下のサイトでは、pdfファイルとして一般に公開もしているようです。
HOME >> 技術トピックス
http://www.ulsystems.co.jp/technology-topic028-0 …
>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 …
No.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/cshar …
それぞれの流派では、中心に据える概念が違います。
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
No.15
- 回答日時:
#1 です。
> OOPを理解していると自負されている方は数多くいらっしゃることは
> 言うまでもなく、OOPについて説明している書籍はかなりあります。
> しかしながら、説明するキーワードは共通していても、
> 説明内容が各々で発散しすぎていると感じております。
これは仰るとおりです。
用語の揺れとしては、手前味噌ですが
http://d.hatena.ne.jp/bleis-tift/20090201/123342 …
の他にも、オブジェクト・クラス・インスタンスという用語にも人によって揺れがあります。
> (あくまで私の見解なのですが、もし、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 原則・・・ももういいですね。
それ以降は長くなるので省きますが、「機能とデータを併せ持ったモノ」という考え方では、よい設計は生まれません。
クラスをそのように取り違えているこの文書もまた、あまり参考にすべきではないかもしれません。
まぁそれを言ったら、この意見も「クラスは機能とデータを併せ持ったモノだ」という意見をもつ人から見れば、
あまり参考にすべきではないものでしょう。
要は「何を正しいとするか」なのでしょうけど、「クラス = データ + 手続き」という考え方からはよい設計が生まれないと言うことを
「デザインパターンとともに学ぶオブジェクト指向のこころ」により知ってしまったので、
自分の考え方はこの本が「基礎」になっています。
No.14
- 回答日時:
#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つの特徴が付いてくるということです。
・カプセル化
・継承
・ポリモーフィズム
ご回答、ありがとうございます。
(返信が大変遅れてしまい、すみません。)
教えて頂いたページを拝見しました。
>「デザインパターンを読み解く」
>http://www.happiese.com/system/dpattern.html
オブジェクト指向が全く分かっていなかった頃、
ご紹介頂いた「Java デザインパターン徹底攻略」を
読みました。
当然理解できなかったのですが、それでも、
何か似ているようなパターンがあるな、と素人ながら
思っていました。
現在、オブジェクト指向がやっと分かりかけてきている状態なので、
デザインパターンを理解するのはまだ先になりそうですが、
上記ページでは、それを分類分けされている点がとても
いいと思います。(頭が整理できると思います。)
将来、必ずこのページをまた訪れようと思います。
>オブジェクト指向
>http://www.happiese.com/system/objectorient.html
このページはいいです!
(後半は理解できていませんが、、、)
まさに手続き型とオブジェクト指向型の対比が紹介されていますね。
このページの著者がオブジェクト指向が有効であることを
述べていますが、必ずしも「オブジェクト指向が絶対にいい!」
なんて言っていません。
こういうことを書けるのは、手続き型、オブジェクト指向型両方を
きちんと理解されているからでしょうね。
(こちらのページも早速ブックマークに入れました。)
とても有効なページをご紹介していただき、ありがとうございました。
No.13
- 回答日時:
> 本当にオブジェクト指向プログラミングっていいのでしょうか?
この手の話は議論が絶えないので違う観点からひとつだけ。
この手の質問を大学時代に先生に投げかけてみたことがあります。
先生の話によると、昔どのプログラム言語が優秀なのか調べる(?)ため、
言語毎にチームを作り、どの言語が一番早くシステム作れるか競う大会が行われたそうです。
当時オブジェクト指向は世の中には全く知られてなかったわけですが
オブジェクト指向を世に認知させるべく、smalltalkを作った研究者も参戦したそうです。
そしてその大会の第一問が、「次の要件を満たすシステムを作れ」という内容で
各チームがそれぞれの言語でシステムを作りました。
そして第二問で、「作成したシステムについて、次の通り仕様を変更せよ」と出題され、
このとき最も早く完了したのがsmalltalkを用いたチームだったそうです。
これがオブジェクト指向が「仕様変更に良い」とか「開発効率が良い」と言われる所以(噂!?)だそうなんですが
先生はこの話のあと、次のようにも付け足していました。
「オブジェクト指向の「オ」の字も登場していなかった時代に
オブジェクト指向を考えた人たちが作るわけだから
そんな優秀な人がやるならsmalltalkだろうがcだろうが優勝できるっしょ!」
まぁ、これは大学時代に先生から雑談半分で聞いた話で
あまり定かな情報ではないので参考程度にしておいてください。
しかし私もオブジェクト指向が良いというのは
話題性だけが一人歩きしている感じが否めないですね。
世の中のトレンドというのは
本当に正しいものだけがいつもまかり通っていると
必ずしも言えないときもあると思います。
Cをよく知っている人なら、Cで作成した方がキレイなコードを書けるでしょうし、
Javaをよく知っている人なら、Javaで作成した方がキレイなコードを書けると思います。
誰かも言っていますが、結局のところプログラマー次第となる問題かと思います。
(余談ですが、Linuxに入っているような一般的な(OSSなどの)ソフトはCで書かれているものが多いですしね!)
この回答への補足
ご回答、ありがとうございます。
(返信が遅くてすみません。)
>Cをよく知っている人なら、Cで作成した方がキレイなコードを書けるでしょうし、
>Javaをよく知っている人なら、Javaで作成した方がキレイなコードを書けると思います。
>
>誰かも言っていますが、結局のところプログラマー次第となる問題かと思います。
>
>(余談ですが、Linuxに入っているような一般的な(OSSなどの)ソフトはCで書かれているものが多いですしね!)
全く、そのとおりだと思います。
#2さんの返信でも申し上げたように、
その言語がいくらオブジェクト指向言語でも、
それを扱う人間が使いこなせないと意味ないですからね。
現在、VC++でなく、C++の教本を読み始めて初めて
「オブジェクト指向言語ってこういう感じで組むんだ」
と分かり始めてきました。
ご回答、ありがとうございました。
No.12
- 回答日時:
手続き型プログラミングより
オブジェクト指向プログラミングのほうが
統合開発環境でインテリセンスを有効利用できます。
クラスを単なる名前空間と関数の塊にするのは簡単なので
オブジェクト指向型で組んで失敗したと思ったことは無いです。
個人的には適切に構造化できていればそれはそれで良いと思いますし。
Javaのアプレットはページをリロードするだけで新しいインスタンスが作成されるので
マルチインスタンスを意識してコードを書いていないと大変なことになります。
最近のシステムでは手続き型で組んで失敗したと思うことは多いです。
純粋に手続き型で書かれたコードは使い回しが困難です。
ご回答ありがとうございます。
(本当に遅い返信ですみません。)
お陰さまで、少しずつですが、オブジェクト指向プログラミングが
理解し始めてきました。
(今まで点であった知識が、線で結ばれ始めています。)
統合開発環境(?)は、VC++6とVC++2005(ExpressEdition)の
VisualStudioを使用しましたが、クラス化すると
関数ベースでコーディングしていたときよりも、
使いやすく感じます。
>純粋に手続き型で書かれたコードは使い回しが困難です。
今となると、困難だったのかなかなぁと思います。
(私の設計が悪いせいかもしれませんが、
関数を作るのに、結構考え込みました。)
クラスにすると、コーディングの量は増えましたが、
簡単にメンバ関数を追加でき、そのクラス関数同士を
組み合わせて新クラス関数をつくったりしているので、
これが使いまわしが聞きやすいって事なのかなぁ、と
思っています。
ご助言、ありがとうございました。
No.11
- 回答日時:
私も初心者で、Delphiなんですが、、、一応クラスやオブジェクト指向の事は分かります。
Delphiは基本的に関数でも、クラスでもOKです。
オブジェクト指向もサポートされています。
で、私がたどり着いた答えは、オブジェクト指向は便利だけど、面倒。
とくに、私のような日曜プログラマでは、開発するアプリの規模が小さく、1人で作っているので、あまり関係がないと決めました!(←これが大事。苦笑
関数はできるだけ、あとで使い回しができるように、私なりに汎用性を高く作っているつもりですし、困ったことはありません。
だって、オブジェクト指向が生まれる前は、みんな関数でやってたんでしょ?
ただ、SLGを作った時には、あー、クラス化、オブジェクト指向・・・というか、継承やポリモーフィズムって、そう言うことか!確かに、便利だわ!って実感しました。
これは関数ベースでは、ちょっと難しいかもと思いました。
ただ、頭が悪いせいか、未だに、普通のアプリを作る上では、関数ベースです。^^;
外部ライブラリー化したりはしますが、私は基本は関数です。
まぁ、とくに問題はないし、作りながら、先のレイアウトを考える悪いクセがあるので、関数ベースの方が楽だったりはします。
まぁ、ほぼ素人なので、お耳汚し程度で。
ご回答、ありがとうごいます。
(本当に返信が遅くてすみません。)
>で、私がたどり着いた答えは、オブジェクト指向は便利だけど、面倒。
理解できていない私が言うのもつらいですが、
本当に面倒だと思います。
そして、私も手続き型で困った事は全くありません。
SLG(シミュレーションゲーム?)を作る際には、
手続き型だと厳しいのですか?
もし、SLGを作成しながらOOPを学べるような参考書が
ありましたら、教えて頂きたくお願いします。
No.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つのクラスへと落とし込むような、そんなニュアンスが感じられてしまうのです。
ちょっと結局何が言いたかったのか分かりにくくなっているような気もするのですが・・・
また、何かあれば書いていただければ反応します。
ご回答、ありがとうございます。
(本当に、返信遅くてすみません)
多重継承の件、分かりました。
(といっても70~80%くらいですが、、、
あとは実践で理解していけると思います。)
初心者の私としては、多重継承しないように
コーディングしていきます。
>クラス設計ではなく、インターフェイス設計と呼ぶか、
>せめてインターフェイス・クラス設計と呼ぶべきではないでしょうか。
あぁ、なるほど、と思いました。
OOPが理解できないないので、インターフェイスの役割も正確に
理解はしておりませんが、簡単に対象(?)、機能(?)を切り替えられる
というふうに認識しております。
そうすると、
・インターフェイスにくっつくクラスはどれか?
・そのクラス達に共通するものはないか?
・共通したものを基本クラスとする
という思考で設計していけば、OOP設計に近づくことが出来るの
でしょうか。
もし、私の認識が間違っているようならば、ご指摘いただけると幸いです。
No.9
- 回答日時:
個人的な意見です、参考程度にしてください。
手続き型、オブジェクト指向型 での大きな違いは
0から開発をすることを考えると長期なプラットフォームでの開発では
オブジェクト指向で設計してプログラムを簡略化、短期なプラットフォームでは手続き型みたなに感じになります。
開発規模にもよりますが、設計期間がオブジェクト指向型のほうが
時間がかかります。この段階で失敗すると、オブジェクト指向にした意味がない作りになってしまいます。
デバッグを考慮すると、複数の人が同じようなコーディングをさせることで見やすくすることを考えるとオブジェクト指向になります。クラス化により書き方を自由にさせないという利点があります。C,C++で考えると分かりやすいと思います。
クラス=オブジェクト
C,C++の対比で言えば、モジュール(1 File)=クラス
オブジェクトしてどのようなことをするかを考えるかです。
Windowsプログラムで考えた場合、GUIで考えると
ボタン、テキストボックス などのように管理対象をどのようにするかを考えると分かりやすいと思います。
ご回答ありがとうございます。
(だいぶ返信遅れてしまい、すみません。)
やはりOOPで設計する方が、時間がかかるのですか、、、
確かに、以前Javaを勉強してコーディングしていたときも、
コーディングする前に、必ずUMLで
シーケンス図やクラス図を書いておりました。
(不慣れな原因もありますが、)
この手間があるから、とても作業が遅かったことを覚えています。
しかも、そのUMLが正しいかどうか判断がつきませんでした。
そう考えると、手続き型の方が
考えやすく、簡単にコーディングできると思います。
でも、これではずっとOOPは理解できないままなのでしょうね、、、
No.8
- 回答日時:
JavaがメインでしてMFCや.NET関連は全くの無知の者ですが、タイトルが「OOP」ということもあり、少しだけ参戦。
デザインパターンによるJava実践プログラミング
http://ascii.asciimw.jp/books/books/detail/4-756 …
上記の書籍は初版発行が2002年9月21日でして、今となってはかなり古かったりもするのですが(最近の若い人は知らないかな?)、GoFの前にちゃんとAlexander教授(建築学)の紹介がしてあったりとか、各パターンの説明にも「GoFフォーム」を利用し、随所にクラス図やシーケンス図が出てきたりなど、今でもそれなりに良書といえるのではないか、と思っています。その中から、少しばかり紹介。
上記書籍の「はじめに」の所で、『ソフトウェアの抽象化と再利用』というのがあり、その中でp.26の「表1 再利用と抽象化の方法」内で、再利用の種類として以下の10項目を上げています。
・断片的な再利用
・データ構造の再利用
・関数の再利用
・テンプレートの再利用
・アルゴリズムの再利用
・クラス(インターフェイス、ポリモーフィズム、抽象クラス)
・コードライブラリ
・API
・コンポーネント
・デザインパターン
一番上の「断片的な再利用」というのは、CaP(カットアンドペースト)のことでして省くとしても、やはり『抽象化』についてはそれぞれ異なるものの、『再利用性』と『汎用性』については下の項目にいくほど、高くなっていきます。デザインパターンの場合は、どちらも「非常に高い」です。
確かに、デザインパターンを適用さえすれば良い、というわけではありませんが、必然的にクラス設計をしっかりしていけばそのような近い形になっていきますし、クラス単位で考えていくと慣れてくれば「可読性」も向上しますし、修正の際にも、あるクラスだけで他のクラスには影響しないということになり、高い「保守性」も望めますね。
手続き型からOOPへの飛躍の一つに、「関数化とクラス化の違いをきちんと理解しているか?」というのが挙げられるかと思います。質問者さんもまだ2,3冊程度しか読まれていない状態かもしれませんが、もう一歩踏み込んで4,5冊目辺りになってくると、知っている知識がかなり増え、未知の部分のみじっくりと読み進めていけばいいのでかなりスピードもアップしますし、その頃にはより「オブジェクト指向」の理解が深まっていることと思います。頑張って下さい。
ご回答ありがとうございます。
(返信遅れてすみません。)
>手続き型からOOPへの飛躍の一つに、「関数化とクラス化の違いを
>きちんと理解しているか?」というのが挙げられるかと思います。
ご指摘のとおり、恥ずかしながらこの点は十分に理解していません。
(だから、「オブジェクト指向言語っていいの?」って
疑問が私にあるのだと思います。)
ご紹介いただいた「デザインパターンによるJava実践プログラミング」
を今度書店に行って見てみようと思います。
(表紙の印象では、とても難しいそうに感じますが、、、)
とにかく、諦めずにその手の書籍を読んでみようと思います。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Java オブジェクト指向プログラミングの実践本を紹介してください 3 2022/09/19 04:56
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/05/21 02:41
- Illustrator(イラストレーター) イラストレーターの面積を求める 1 2022/04/17 11:05
- Java 複数TBLのオブジェクトを1つの変数(オブジェクト)でまとめて管理したい 1 2022/12/17 00:12
- オープンソース IT用語、ソースとオブジェクト、改変と翻訳と翻案の違いなど どのようにりかいすればよいのですか 1 2022/09/09 10:02
- その他(プログラミング・Web制作) Pythonのライブラリ、randomについて 3 2022/09/20 14:30
- Visual Basic(VBA) Excel VBA オブジェクトマクロ 使用指定について お詳しい方教えてください。 共通エクセルフ 2 2023/03/14 17:26
- 武道・柔道・剣道 ★成長が頭打ち、どう伝えたらいい? 空手道場の指導員をしています。 どう伝えてもあの手この手を試みて 3 2023/04/18 10:44
- その他(プログラミング・Web制作) Pythonのオブジェクトの関数について 2 2023/05/11 19:15
- 経済 ディベートで勝ちたいのですが相手を言い負かせる質問を考えてくれる方募集します。3回同じチームでディベ 7 2023/07/20 15:49
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
スクロールバーについて
-
C#のクラスと継承が理解できま...
-
メソッドの引数にクラス名を渡す
-
Javaでのジェネリクス型パラメ...
-
(vba)他のアプリケーションの右...
-
C# 「データが失なわれる可能性...
-
interface,extend,implementの...
-
JTextFieldの入力制限
-
ContentLengthを確認したい
-
抽象クラスをJUNITでテストする...
-
抽象クラスが継承されているか...
-
オーバーライドとラッパーの違い
-
僕の出身中学校は200人同級生が...
-
「タイプ初期化子が例外をスロ...
-
エクセルVBAで、条件に一致する...
-
今日は こどもの日 で、良い天...
-
配列のメソッド
-
複数の変数を宣言する時、同時...
-
クラス間でのデータ参照
-
変数名の付け方
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C# 「データが失なわれる可能性...
-
「継承されたメソッドの可視性...
-
(vba)他のアプリケーションの右...
-
【C#】クラスのコンストラクタ...
-
VB DLLプロジェクトについて
-
メソッドの引数にクラス名を渡す
-
「ラッパークラス」の存在意義...
-
interface,extend,implementの...
-
c++でのヘッダーファイルの循環...
-
このエラーメッセージの意味を...
-
委譲って何ですか?
-
ゲッターを使わないで変数にア...
-
Javaのインスタンス化の構文の...
-
ファイルパスが取得出来ない(P...
-
ASP.NETでの共通コードの書き方...
-
Commons-Discovery.jarとは?
-
デバッグ時に「Source not found」
-
JTextFieldの入力制限
-
JavaのimplementsをC言語で例え...
-
オーバーライドとラッパーの違い
おすすめ情報