ウィリアムのいたずらの、まちあるき、たべあるき

ウィリアムのいたずらが、街歩き、食べ物、音楽等の個人的見解を主に書くブログです(たま~にコンピューター関係も)

Ruby1.9、Windowsで-その6 クラス3 継承と横断的関心事

2008-05-07 16:23:13 | Ruby

 久々の、シリーズ「Ruby1.9、Windowsで」です。
 今、クラスの書き方をやっていて、クラスを書いて、属性の変数を書くところまできました。
 今日は、継承(Javaのextends)と、横断的関心事が書けるモジュールについてやります。

 なお、このシリーズでも、< > ¥は、断りのない限り、本当は半角です。




■継承

 継承を使うと、継承元に書いた属性やメソッドを継承先に書かなくて済みます。
 ・・・ってことなんですけど、そーいう技巧的な話ではなく、ふつう、階層関係があるときに利用します。

 クラスにおいて、「動物」、「人間」、「日本人」のように、階層関係があることがあります。
 言うまでもなく、例の場合、動物の一種が人間で、人間の一種が日本人なので、

    動物-人間-日本人

 という階層(親子)関係があります。

 このとき、動物全体に共通な話(性別とか)は、動物で定義しましょうと。そーしたら、人間でも、日本人でも、再定義しなくても使えますよと・・
 そうすれば、それぞれの種固有の属性(「人間」の「肌の色」とか)のみを子供の(ここでは人間の)クラスで定義すればいいよねと・・
 ただし、動物全体で、機能的には同じでも、それぞれの種によって違いがある場合もあるでしょう(走る=動物だと4つ足、人間は、2足歩行)。そこは、それぞれの種(子供のクラス=ここでは人間)で再定義してねと・・

 こーいう親子関係を継承といいました。




■継承のあらわしかた

で、Rubyの場合は、< (ほんとうは、半角)で、クラスのところに書いて表現します。

class Ningen < Dobutu

みたいなかんじで、親子をあらわします。
サンプルは、こんなかんじ。

class ZZ
 attr_accessor :a
 def putme()
   puts @a
 end
end

class ZZZ < ZZ
 attr_accessor :aa
 def putme()
  puts @aa
 end

 def putmea()
  puts @a
 end

end

(上記< > ¥は、本当は半角)

上記の場合、ZZが親で、

class ZZZ < ZZ

で継承の宣言をしているため、ZZZでは、
@aaというのが使えるのはもちろん、
ZZで宣言している
@aも使えます。

また、ZZZのputmeは、ZZでもputmeがあるけど、
ZZZで再定義されているので、
ZZZにあるputmeを実行、
  つまり@aaが出力されます。

なので、
b=ZZ.new
bb=ZZZ.new

b.a = 100
bb.a = 200
bb.aa = bb.a + b.a

b.putme
bb.putme
bb.putmea

(上記< > ¥は、本当は半角)

とやると、
b.putmeでは、b.aの値である100,
bb.putmeでは、bb.aaの値である300
bb.putmeaでは、bb.aの値である200

が表示されます。




■アスペクト指向と横断的関心事

 で、オブジェクト指向で、とくにプログラミングファースト開発みたいなかんじで書いた場合、クラスのような、本来の意味的には関係ないんだけど、共通の機能というのが出てきます。
 とくに、デバッグ・テストに関するものや、チェックに関する機能など・・・

 数字チェックとか、トレース、ログの処理とか・・・

 こーいうのは、どんなクラスにも(クラス横断的に)出てきてしまう、共通の事柄(=関心事)です。

 っていうことで、横断的関心事と呼ばれ、これを切り出して、簡単に書けるようにしたのが、アスペクト指向なわけですが、このアスペクト指向のような、横断的関心事を、簡単に実装できちゃう機能が、モジュールです(って、モジュールが横断的関心事のためにでてきたのかは?だけど、まあ、そんなのにも、使えちゃうと思うわけですよ)




■moduleの使い方

 で、そのmoduleの使い方なわけですが、

1.moduleで、メソッドを書きます。
2.それを、各クラスでincludeしちゃいます。
3.そーすると、各クラスで使えます。

こんなかんじ
module DebugModule
  def errorDisp(n)
    puts n
  end

  def traceDisp(n)
    puts n
  end
end

class ZZ
 include DebugModule
 attr_accessor :a
 def putme()
   traceDisp("putme in")
   puts @a
 end
end

(上記< > ¥は、本当は半角)

DebugModuleで、errorDispとtraceDispを宣言しています。
このメソッドが横断的関心事。

で、各クラス(といってもここではZZクラスしかないけど)で
include DebugModule
をします。

そうすると、DebugModuleの中にある、traceDispが使えます。

なので、ここで、
b=ZZ.new
b.a = 1
b.putme

とすると、

putme in
1

と、まずはじめのtraceDispの処理結果である、putme inが表示され、
そのあとに1と表示されます。




こんかいはここまで。


  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

修正可能なシステム その6 外部設計部分(2)

2008-05-07 11:46:59 | Weblog

 シリーズ化してしまった?修正可能なシステムです。
 今、ここで書いた外部設計部分をやっていて、前回は「(5)業務プロセスを画面にする」だったので、今回は「(6)サーバー側DBアクセス部分の設計」です。




■DBアクセス部分の修正

 DBアクセス部分、つまり、テーブルと、アクセスクラス部分を作成・修正するわけですが、
 (ファイルでも、アクセス部分を作成・修正するわけですが)
 この場合、2通り考えられます。

(1)新規DBアクセス(ファイル)部分追加
 このときは、簡単です。新しく追加すればよいだけですので・・
 既存のプログラムとは独立して動くことが多く(場合によっては、一貫性の問題があることはあるんだけど・・)

(2)既存のものの修正・削除を含む場合
 既存のDBアクセスを修正・削除する場合は、そうはいきません。
 新規システムを開発しようとして、既存のシステムの修正前に、DBアクセス部分を修正・削除してしまうと、コンパイルエラーになったり、おかしなことが起きたりします(もちろんこれは、DBアクセスには限らないけどね)

 で、どうするか・・以下、この(2)について説明します。




■バージョンをつけ、混在しないようにさせる

 このとき、バージョンをつけ、混在しないようにさせる方法があります。

 メソッド自体をきりわけてもいいけど、それはわけわかんなくなるので、
 引数にバージョンを追加したり(あるいはハッシュマップで引数をわたし、そこにバージョンをいれる。バージョンが入ってないのは、一番はじめにこのテーブルが出来たときのものとする)、引数の値のオブジェクト(バリューオブジェクト)の型を変えてみたり・・などなど・・

 で、こうすると、このバージョンのときは、この値を返す・・っていうことで、既存のものと、新規のものを同時並行的に開発しても、問題はなくなります。

 なので、このように設計することも考えられます。




■ただし、開発では・・

 ただし、開発では、スタブをいれておいて、自分の環境では、既存のDBのスタブを使うか、新規のDBのスタブを使うか、切り分けておくのが、安全ではあります(し、バージョンは、下手すると複雑になるので、いいとはいいきれない)。




ってなかんじですかね。この話題は、ここまで。



  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする