[kikainekomocker:28] Re: 非破壊メソッドってどういった意味なのでしょうか?

Ioki Masayuki youzou5 @ hotmail.com
2006年 9月 15日 (金) 00:11:32 JST


伊尾木です。

合田さん、よろしくお願いします。

>坂井さん
まかされました!笑

非破壊メソッドですが、immutable なんて言われたりもしますが、あまり一般的な言
葉ではないかもしれませんね。。。
非とつくようにこれは破壊メソッドの逆です。
破壊メソッドというのは、自分自身を破壊してしまうメソッドのことです。
例としては以下のようなものです。rubyの文字列クラスのstripメソッドを取り上げ
ます。前後の空白を削除するメソッドです(Javaでいうtrimです)

str="  a  "
puts str.strip #-> "a"
puts str #-> "  a  " 何も変わらない
puts str.strip! #-> "a"
puts str #-> "a" 自身が変更された

分かりますでしょうか、最初の「strip」の呼び出しでは確かに前後の空白を削除し
た値が表示されますが、str自身は何も変更されていません。ところが、次の
「strip!」では、自分自身が変更されています。
このように自身の状態を変更してしまうメソッドを破壊メソッドとよび、自分自身を
何も変更しないメソッドを非破壊メソッドと呼びます。JavaのStringは非破壊メソッ
ドばっかりですね(こういうときにimmutable な性質を持つといわれます)

で、機械猫モッカーでは、この非破壊メソッドを見つけることは結構大きな意味があ
ると考えています。
というのも、機械猫モッカーは一度テストコードを実行して、その結果を保存し、そ
れを再生できる形で擬似クラスを生成します。つまりどのようなメソッドがいつ、何
回、どう呼ばれたかを正確に記録しているわけです。
そしてその記録されたとおりに呼ばれる限り、擬似クラスは正しく動きます。
ところが非破壊メソッドではそれがそうも言ってられないのです。
例えば何かのgetter/setterメソッドがあったとします。この場合

hoge.setI(1);
hoge.getI(); #-> 1

が返ってくるテストが書かれたとします。
このときモッカーは「set(1)Iが一度呼ばれ、その次にgetIが一度呼ばれた」と記録
します。
では、実際にその擬似クラスを使用する場面において、次のような呼び出しかたをさ
れたらどうなるでしょうか。

hoge.setI(1);
hoge.getI(); #-> 1
hoge.getI(); #-> ??

最初のgetIの呼び出しはテストで定義されている動作のため、問題なく動きます。で
は2度目のgetIは?
実はこれは動きません。バージョン0.9.6 ならば0を返すか、例外を投げて死んでし
まいます。
これはテストで定義された動作ではないからです。(モッカーはgetIが2回も呼ばれ
るなんて想定できないからです)

しかし、直感的にいって、ここはgetIがまた「1」を返して欲しいところなんです。


これはモッカーがあまりにも正しくメソッドの呼び出し順を見ていることに起因しま
す。そこでこの厳しすぎるテストへの依存をやめ、ある程度直感的な動作ができない
かなぁと考えています。

坂井さんが仰ったように「パラメータの限界値、同値分析、NULL値対応など」もいず
れ対応したいのですが
今のところこの非破壊メソッドなどをみつけ、メソッドの呼び出し順を緩和すること
からはじめたほうが楽かなぁと考えている次第です。

(てか、伝わってますでしょうか・・・僕、文下手なんです・・・汗)

もし他の方でも、意味わかんねーとか、こんなアイデアどうよ、みたいな方がおられ
ましたらご遠慮なくお願いいたします。

長文になりましたが、よろしくお願いします。




kikainekomocker メーリングリストの案内