ブログ「サイバー少年」

ブログ「サイバー少年」へようこそ!
小学六年生ごろからプログラミングを趣味にしている高校生のブログです。
勉強したことについての記事などを書いています。フリーソフトも制作、公開しています。
(当ブログについて詳しくは「ブログ概要紹介」を参照)

サイバー少年が作ったフリーソフトは「サイバー少年の作品展示場」へ

カプセル化が上手く出来ぬ

小遣い帳ソフトのプログラムを書いていて思ったのですが、
私はカプセル化されたオブジェクトの構築が下手ですね…。


カプセル化っていうと、下図のようにするべきじゃないですか。

(矢印はそのクラスへの依存を表し、ただし逆方向への依存は表していません。)


理想的なカプセル化されたオブジェクト
理想的なカプセル化されたオブジェクト


こんなふうに、それぞれの役割をこなすクラス(細かく言うとインスタンス)がたくさんあって、

メイン進行者的なクラス、要するにエントリーポイント的なクラスから、それぞれ呼び出していくのが理想的なカプセル化だと思っています。

それで、部品は取り替えようと思ったら簡単に取り替えられるわけです。



しかし、私の書いたプログラムを読み返してみると、下図のような感じになっていました。


ミルフィーユみたい
ミルフィーユみたい


クラスが階層的になってしまっているのです。

下位層のクラスに機能を付け足した上位層のクラスを定義して、
さらに機能を付け足した上位層のクラスを定義して…

それで最終的にメイン進行者的なクラスに行き着くわけです。


まぁ、階層化するという考えは、ネットワークもそうですし、悪い考えではないと思うのです。

一応、どこかの層を交換しても、1つ上の階層のクラスだけに影響をとどめることが可能な設計なわけですよ。


とは言っても、たまに上位層のクラスが1つ下ではなく、2,3つ下の層に直接アクセスするという行儀の悪いこともしちゃっていますので、

その場合は上位層に影響が出ることもありますね。
(まぁ、1つに詰め込むのと比べれば…)


そういう行儀の悪いアクセスをしてしまう原因も、この階層的設計に問題があると思うのです。

「この機能が単体で欲しい!」ってなったときに、やはりその機能を実装した層に直接アクセスするしかないですから。


ほかにも、階層設計でやるとプログラムが膨大になって層が増えたときに管理が難しいですし、

そもそも、カプセル化とはこういうことではありませんよね…。



最初に述べた理想的なカプセル化を心がけているにも関わらず、
どうしても後者のような階層的な設計になってしまうのはなんなんでしょうかね…。

本当に不思議ですね。
経験不足かな?

というわけで、直したい癖だなぁと思っております。




本題からそれますが、最近は書いたプログラムが概ね意図したとおりに動くので嬉しいです。

これは経験のおかげでしょうかね。

なら、そのうちクラス設計も上手くなるのだろうか…。

tag:

コメント

ミルフィーユヽ(゚∀゚ )ノ パッ☆
新しい時代のクラスライブラリですね!

2つ図がありますが、両方共、ある意味プログラミングあるあるですね~
どうすればうまくいくか・・・?
そういえばソ開時代や応情初期はこの手のクラスデザインのオブジェクティブ・バイ・ベストエフォーテッドに関する自由論述問題(午後問)が結構出ていたように思いますが(そういうのに対して、このブログで書いているような解答ができれば文句なく満点と言っていいと思います)、ただ最近は応情もこじんまりとした出題が増えてきた気がします。私みたいなのにはそっちの方が有利ですが…

  • 2014/02/03(月) 18:38:31 |
  • URL |
  • ポケモンYZ #-
  • [ 編集 ]

Re: ポケモンYZ

本当にミルフィーユみたいな感じですよね(笑)

新しい時代のクラスライブラリというか、私はこのミルフィーユ設計は望ましくないと思っています。
本当なら1つ目の図のように設計したいのですが、書いているうちにミルフィーユになってしまう…と。

応用情報技術者試験、頑張ってください。

継承より委譲ってしってりゅ~???

  • 2014/02/04(火) 11:36:43 |
  • URL |
  • 挽き肉屋 #-
  • [ 編集 ]

Re: 挽き肉屋

後者のミルフィーユ的な設計でも、継承ではなく委譲を使っています。
ただ、構造のイメージは継承に近いわけです。

本当は前者の設計ような“THE 委譲”といえる設計がしたいです。

なんていうか、カプセル化って、クラスの中の変数を直接触らせないっていうアレのことだと思ってました

int xをprivateにして、publicのsetX()とgetX(int _x)を作るみたいな

  • 2014/02/09(日) 17:30:09 |
  • URL |
  • AsaBon #-
  • [ 編集 ]

Re: AsaBon

カプセル化という言葉は色んな解釈をされているようです。

私は「依存関係にある機能(メソッド、フィールド)のセットを1つのオブジェクトにまとめる事」という意味だと思っています。

1つの機能を実現するのに2つ以上のオブジェクトを使うことはなるべく控える、ということです。
どうしても2つ以上のオブジェクトで実現させたい場合は、そのオブジェクト達を1つのオブジェクトに内包させて、使用者には1つのオブジェクトのように見せるように、なるべくします。

参考までにWikipediaのリンクを載せておきます。

カプセル化 - Wikipedia
http://ja.wikipedia.org/wiki/%E3%82%AB%E3%83%97%E3%82%BB%E3%83%AB%E5%8C%96

少し内容がずれるかもしれませんが、
リファクタリングについて、調べると、
参考になるかもしれません。

ttp://www.atmarkit.co.jp/fdotnet/special/refactoring/refactoring_01.html

所謂、ソースの体質改善というやつです。

  • 2014/02/24(月) 12:00:40 |
  • URL |
  • 通りすがり #-
  • [ 編集 ]

Re: 通りすがり

ありがとうございます。
Visual Studioにも「リファクタリング」という項目がありますが、よく考えたことは無かったです。

規模が大きくなってくると次第にオブジェクトどうしの関係もメチャクチャになってくるんですよね…。

VSにあるのは、支援機能になります。
リファクタリングの概念を元に使うと便利な機能って感じです。
で、概念的な事は、下記に纏めてあります。
(もうちょっと、いいサイトがあればいいのですが、検索しきれませんでした)
ttp://hamasyou.com/blog/2004/06/29/post-8/
javaでリファクタリングが話題になった時は全部で70程度の
項目があがっていました。しかし、大事な20項目程度を理解すれば、
ほどほどにいい感じになります。
javaだとサンプルソースがあるんですが、C#だと検索しきれませんでした。
他にもソースの改善に、GoFデザインパターンというのもあり、参考になるかもしれません。
ttp://itpro.nikkeibp.co.jp/article/COLUMN/20051123/225074/

  • 2014/02/25(火) 01:44:18 |
  • URL |
  • 通りすがり #-
  • [ 編集 ]

Re: 通りすがり

確かに、VSのリファクタリングに「メソッドの抽出」とかいう項目がありましたね。
URLありがとうございます。

本当はリファクタリングが要らないようなコードを初めから書けるのが理想型なんでしょうけど、難しいですよね~。

GoFデザインパターンは以前、少し挑戦したことがあります。
結局Factory(AbstractFactoryだったかな?)パターンとSingletonパターンしか覚えられませんでしたが…。

オブジェクト指向設計を構成する要素は大体覚えたわけですけど、デザインパターンはそのゴールみたいなものですね。

リファクタリングなしで、書くのは難しいですね~。
製作期間が短かったり、難しいロジックな場合は特に。
で、要望の追加などになった時に、まとめてど~んという感じです。
それでも、テストコード作成に1ヶ月。
実際のコード修整に1ヶ月とか、、、数ヶ月単位ですねえ。。。
もちろん規模によりますが。
コードのパターンを見てれば、
その書き方を思い出してまねる事も増えるんで、要領よくはなります。

  • 2014/02/28(金) 12:34:14 |
  • URL |
  • 通りすがり #-
  • [ 編集 ]

Re: 通りすがり

まあ、完璧なものは書けないですからね~。

コードのパターンを覚えるというのは有効な方法だと思います。
そうなってくるとGoFパターンを覚えることに帰着しますね。

今後オブジェクト指向言語を使って本格的にプログラムをしていく場合は、
こういうのを覚える必要も出てきますね。

コメントの投稿

トラックバック

トラックバック URL
http://cyberboy6.blog.fc2.com/tb.php/322-8f6482f6
この記事にトラックバックする(FC2ブログユーザー)

当ブログをご利用(閲覧等)になる場合は必ず「当ブログの利用規定」をお守りください。