NET - みる会図書館


検索対象: ひなた先生が教えるデバッグが256倍速くなるテクニック : 実践的ソフトウェアデバッギングの手法
21件見つかりました。

1. ひなた先生が教えるデバッグが256倍速くなるテクニック : 実践的ソフトウェアデバッギングの手法

ノた / し ~ デ廴 = 。りつ倍くなるテクニック 「いえ、 2006 年ですら、 pub ⅱ c なメンバ変数は一切使わず、 property にしてまし た。たとえば . NET F 「 amework 2. O の構造体にリスト 5 のようなものがあります」 マリスト 5 . NET Framework 2. () の Rectangle 構造体 public struct Rectangle { public static readonly Rectangle Empty; private int x; private int y; private int width; private int height; ひなた先生が教える ( 中略 ) public public pub [ i c public public ( 後略 ) Size Size { get; set; } int X { get; set; ) int Y ( get; set; } int Width { get; set; } int Height { get; set; } 「そうかな ? p 「 ope は y はメソッド呼び出しだから in ⅱ ning 注 3 されないと、何度もア クセスする部分では ( その呼び出しのオーバーヘッドが ) 利いてくるのだけど ? VisuaI Studio 2005 でそんな最適化してなかっただろ ? 」 「ええ。そうでしたね。ということは、 ( 僕は使ったことはありませんが ) パフォー マンスが気になるところは仕方なくラクダケースにして pub ⅱ c にしていたかもしれ ません ( リスト 6 ) 」 V リスト 6 pub ⅱ c なメンバ変数 public struct MyRectangle ( publi c publi c publi c public public 注 3 static readonly Rectangle Empty; int y; int width; int height; こで言う「 inlining 」とは in ⅱ ne 展開のことである。メソッドを呼び出し側に埋め込むことによって関数呼び出しのオー バーヘッドを取り除くコンパイラの最適化のことを意味する。 例 ) VOid a(int n) { return n + 1 ; } void b(int n) { return a(n ・ 2); } ならば、メソッド b において、メソッド a の呼び出しを in ⅱ ning すると VOid b(int n) { return n ・ 2 + 1 ; } のように最適化される。 238

2. ひなた先生が教えるデバッグが256倍速くなるテクニック : 実践的ソフトウェアデバッギングの手法

0 ル多プ ! こ。うつ第くなるテクニック 「えーと、最悪のシナリオではそうなりますね」 「たとえば、図 3 のように . NET F 「 amewo 「 k を直接呼び出すのではなく、 . NET F 「 amewo 「 k の w 「 appe 「クラスを用意して、 . NET F 「 amewo 「 k を呼び出すのをや めることはできないのかしら ? 」 マ図 3 . NET Framework を直接呼び出さない AppIication デバッグが ひなた先生か教える - 0 0 0 . N ET F 「 a m ewo 「 k . NET Fra mework Wrappe 「 . NET F 「 amework 2. O . NET Fra m ework 3. x 「ええ、そうすれば、 . NET F 「 amewo 「 k のバージョンが上がったとしても、『 . NET Framewo 「 k Wrappe 「』の部分だけ修正を加えれば、 Application の部分には一 切手を加えずとも ( 原理的には ) 動かせますね。 しかし、 . NET F 「 amewo 「 k は結構規模が大きいのでこれを w 「 ap するだけでもずい 0 ぶん大変な作業になるでしようし、それに・・・」 ケンイチはロごもった。 「それに ? 」 ひなた先生は、続きが気になって気になってしようがない。さすがに 白タイムか ? とは思わないが。 0 例外を投げるクラスを wrap するの巻 いよいよ愛の告 「この問題、意外とややこしいのですよね。たとえばですね、『 . NET Framework WrapperJ の部分ですが、リスト 6 のように F ⅱ e クラスを w 「 ap しているとしますね」 212

3. ひなた先生が教えるデバッグが256倍速くなるテクニック : 実践的ソフトウェアデバッギングの手法

第 11 回例外処理の考え方 .NET Framework の投げる例外の巻 「ところで、ケンイチ君 ? 」 「は、はい」 211 しいバージョンが出ることに何らかの書き換えを行わなければならないってこと ? 」 「汎用性のあるクラスを書いていても、 . NET F 「 amewo 「 k を直接呼び出す限りは、新 なるでしようね。たいていは何も書き換えなくとも動くのですが」 「その場合は、 1 . 1 用に開発したクラスを 2. O で動くように書き換える作業が必要に いるプログラムに流用したい場合は ? 」 「 . NET F 「 amework 1 . 1 用に開発したクラスを、 . NET Framewo 「 k 2. O で書いて いので」 のほうで動かすことができるのです。そうすればソースの書き直しが一切発生しな を . NET Framewo 「 k 1 . 1 と 2. O が入っている環境で動かすときに 2. O ではなく 1 . 1 「 Side-by-Side 実行というのは、 . NET F 「 amework 1 . 1 用に作った実行ファイル 「 Side-by-Side 実行ってなあに ? 」 きなんでしようね」 「それは、あるでしようね。ですので、その場合は、 Side-by-Side 実行を用いるべ 性っていうのはないの ? 」 F 「 amewo 「 k がバージョンアップしたときに、メソッドの投げる例外が変更になる可能 「私、あまり . NET F 「 amewo 「 k を使ったことはないのだけれど、今後、 . NET 「はい」 「ケンイチ君は、 . NET F 「 amewo 「 k を使って開発してるよね ? 」 ケンイチは、いよいよ愛の告白タイムか ? と思って、胸がどぎまぎした。 0

4. ひなた先生が教えるデバッグが256倍速くなるテクニック : 実践的ソフトウェアデバッギングの手法

テパッグが くなるテクニック ひなた先生が教える そのメソッドはどんな例外を投げるのか ? の巻 「ケンイチ君は、そもそも、そのメソッドが投げる例外というのはどうやって調べ ているの ? 」 「 . NET F 「 amework のメソッドならば、インテリセンスが表示してくれますね ( 図 2 ) 」 ▽図 2 インテリセンスがメソッドが投げる例外を表示しているところ 「なるほど」 ひなた先生は何やら、いまひとつ納得のいかないような表情だった。 void SomeFunct ion() リ 5 i n g ( F ⅱど引 - 「 & f s 朝 Get LastAccessTimelJtc 朝 Get LastVfr iteTi me 朝 GetLastV1h iteTimelJtc ー 0 Move 朝 Open 0 ー F ilestream F i le.OpenRead (string path) 読み取り用の既存のファイルをきます。 朝 OpenText 、 ite 列外 : 、匪記旧 ytes System.Unauthorized Access Exceptlon System.lO. PathToo LongExcept ion 、記 AllLines System.Argu ment NI. 川 Except ion System.Llnauthor ized Access Except10n System.IO 下 ileNot Found Exception System. NotSupported Except 朝 1 System. Argument Except ion Syste m.lO. D irectoryNot FoundExcept ion 「これは、ドキュメントに含まれているのよね ? Visual Studio 注が自分の書いたメ ソッドに対しても自動的に投げる例外を調べて表示してくれているわけではないの よね ? 」 「あー、そうですね。自分が書いたメソッドが例外を投げる場合は、その例外の型 もドキュメントに書いておきますね」 「自分が書いたメソッドが投げる例外をどうやって調べるの ? 」 「 VisuaI Studi0 が調べて勝手に書いてくれれば良いのでしようけれども、そうはな っていないんですよね。ですので、ひとつひとつ手作業で調べながら書いています」 注 ここで VisuaI studio とは現時点での最新版である Visu studio 2005 / 2008 を指している。 208

5. ひなた先生が教えるデバッグが256倍速くなるテクニック : 実践的ソフトウェアデバッギングの手法

0 ノ多。匕りの - ー : ー , くなるテクニック テパッグが ひなた先生が教える 「ええ。 shallow copy とも言えますが・・・どちらかと言うと、 C + + の場合は bitwise c 叩 y ( ビット単位のコピー ) ですね」 get は read と違うの巻 「ケンイチ君のおかげでなんとなく記憶が蘇ってきたよ」 「あの、 C # のプロバティの構文なんだけど、 get と set ってどこか直観に反するんだ 「どうしてですか ? 」 「それは良かったですね ! 」 0 使って、値を w 「 ite するときに set を使うような印象を受ける」 「 get は取得する、 set は設定するって感じがするから、値を「 ead するときに get を 臼 「あー 言われてみればそうですね」 を 「だけど、実際は、「 ead するときも w 「 ite するときも get だ。オブジェクトを get し て、そいつのメソッドで「 ead なり w 「 ite をしなくてはならない。オブジェクトを設 定しなおすときだけ set だ。このへん、つい錯覚してしまう」 「その経験は私もあります・・・。その錯覚の原因は、 C の関数で引数にポインタやら参照や ら渡しているのに違和感があるのと同じ原因かもしれませんね」 「そもそもなぜ、 C # のプロバティは引数を取れないんだ ? バラメータを取らせても らえないと、どうにも不便だ」 「さあ・・・」 「はい。それは区別せずに済むならそれに越したことはないと思います」 う気がしてきた」 「あとさ、参照と値型とを区別しないといけない言語は良くないんじゃないかとい 286

6. ひなた先生が教えるデバッグが256倍速くなるテクニック : 実践的ソフトウェアデバッギングの手法

第 11 回 マリスト 6 File を wrap する例 class MyFile { public FileStream OpenRead(string path) return File. OpenRead(path); 「うん」 例外処理の考え方 「しかし、 . NET F 「 amewo 「 k のバージョンが上がったときに、新たに FiIe. Open の 投げる例外が追加されたとします。 この場合、 MYF ⅱ e. OpenRead を呼び出す側は当然そんな例外のことは知りません から、 catch も何もしていません。ということは、 MYFiIe. OpenRead で、その新 たに付け加わった例外を " 握り潰す " 必要があります」 「うん、そうなるよね」 「ところが、そのような握り潰しをして良いのかという問題があります。その例外 が致命的なエラーを意味しているかもしれません。この場合、致命的なエラーを表 す他の例外にすり替えることが考えられるのですが、すり替えるべき適切な例外が 存在していない場合、このアイデアはうまく行きません ( リスト 7 ) 」 213 下において、そのメソッドを適切に w 「 ap するというのは非常に難しいのです」 「結局のところ、メソッドが投げうる例外があとから追加されるかもしれない状況 「そうね、なるほど」 throw new FileNotFoundException(); catch (NewFatalException) return File . OpenRead(path); public FiLeStream OpenRead(string path) マリスト 7 例外をすり替える

7. ひなた先生が教えるデバッグが256倍速くなるテクニック : 実践的ソフトウェアデバッギングの手法

第 14 回 vo i d I n i t ( ) setB001Delegate = delegate(bool b) { myCIass. B00LVaLue = b; } 冫 ポインタと参照との関係 「正直ダサい。ダサすぎて俺には耐えられない。 b00 にがあれば済むところ、なぜ delegate まで駆使しなきゃならないの ? 」 「プロバテイから delegate へ暗黙変換できないのが冗長になっている原因のような 気がしますね。あと、 get と set と両方の delegate を用意しないといけない部分も 冗長で・・・構文としては次のようなものがあればすっきりすると思うのですが ( リス ト 7 ) 」 マリスト 7 プロバティの直接代入構文 b00 [ MyB001Va lue get ′ set:delegate; vo i d I n i t ( ) myBooIValue . get MyBoolVaIue. set 14 myClass . B001Value . get; myCLass. BoolVaIue . set; 「すっきりしてるかなあ ? b00 にと書かせてもらえたほうがよっぽどすっきりするん だけども ? その上のコードを構文糖を用意して、リスト 8 のように書けるようにし てはダメなの ? 」 マリスト 8 プロバティの直接代入構文その 2 b00 [ & MyBoolVaIue; vo i d I ni t ( ) MyBoolValue& myCIass . B001Value; 「良いとは思いますが、構文糖として糖分が高すぎる気もします」 「そうだな・・・何をやっているのか見えなくしてしまうのは、もはや構文糖の範囲を 超えているからな・・・。そうだな。じゃあ仕方がない。値型を参照として扱いたいだ けなのに、もっと単純に書くことはできないの ? 」 281

8. ひなた先生が教えるデバッグが256倍速くなるテクニック : 実践的ソフトウェアデバッギングの手法

第 13 回 関数の返り値はどうあるべきか 「ふむ、なるほどな。ところでさっきの SomeFunc 日 esu は . Ok はやつばり良くない 気がするんだな」 「なぜですか ? 」 「だってほら、リスト 13 のようになっていたら、 if(f00. SomeFunc()==F00. SomeFunc 日 esu に Ok ) のように書く必要が出てくる。この F00. SomeFuncResult. Ok っていうの凄く冗長だと思うんだけど ? これって Visu Studi0 2005 のインテ リセンスが補ってくれるの ? 」 ▽リスト 1 3 SomeFuncResult の定義例 public class F00 { publi c enum SomeFuncResuLt Fi leNotFound FileReadError { Ok public SomeFuncResult SomeFunc() とタイプして〔ネ 5 三ネ〕を押した瞬間に F00. SomeFunc 日 esu はがイン 「はい。 テリセンスの候補として挙がりますね」 「そうなのか。それなら良いんだが。それにしても、読みにくいな、そのソースは」 「 . NET Framewo 「 k では、そういう特定のメソッドが用いるような構造体でも、ク ラスの外に出してしまうことが多いようですね」 「うーん、それはオブジェクト指向のクラス設計としてはややおかしい気もするが、 まあ、ソースが読みにくくなるのを避けるためなのかもしれんな」 「ええ」 インテリセンスと返り値の巻 「そろそろ本題に戻ろう。関数 ( メソッド ) の返り値は、かくあるべき、というよ うな議論はあまり類を見ないし、それゆえ、指針もないに等しい。だから、今から 手探りで探って行かなくてはならない。しかし、どうあるべきかは や開発環 、ロロロ 253

9. ひなた先生が教えるデバッグが256倍速くなるテクニック : 実践的ソフトウェアデバッギングの手法

0 電 .. くなるテクニック 「いや、ケニチ君。間違ってはいないのだが、 Uen を入れ替えるときに同時に F eT も入れ替えなくてはダメなのだよ」 「良くわからないのですが、その FeT の入れ替えというのは、どういうことでし よう ? 」 「 F と T が入れ替わるのだから真偽値が逆になる。つまり、これは、 not ( 否定 ) を とる操作だと思えは良いだろう」 「よくわかりません」 「上の等式は直接的に導き出せるんだ。実際にやってみよう。たとえば、今、 AUB = F という等式が成り立っとする。この等式に対して、 lJen と FeT という入れ 替えをしてみよう」 マ図 5 AUB = F から Uen , F#T の入れ替え A U B = F - - - ① ↓ A n B = T ・ - - ② ひなた先生が教えるデ / ーッグが 0 0 臼 「あっ。なんとなく、 2 項のときのド・モルガン則みたいなものが見えますね。①の 両辺の否定をとると、 ! ( AUB ) = T となって、②の An 白 = T とくつつけると ! ( AIJ B)=T=ÄnB というド・モルガン則が導けますね」 「だろう ? 」 「ということは、同様に 3 項の場合でも AUBUC = F という等式があったとして、こ の項に対して、 lJen と FeT という入れ替えると次のようになりますよね」 188

10. ひなた先生が教えるデバッグが256倍速くなるテクニック : 実践的ソフトウェアデバッギングの手法

0 テパッグが 電 1 ーくなるテクニック 「苦ではないかもしれないけれど、 SomeFunc 日 esu は . Ok なんて書いてあると、ず いぶんと読みにくいと思うんだけども。本当にそんなのが流行ってるの ? 」 「いえ。最近のトレンドで言えば・・・そうですね、たとえば、 . NET Framework では、 工ラーはたいてい例外で返すのが標準的であるため、返り値をエラー要因を表すた めに使うことはあまりありません」 . ~ 「ふーん。そうなんだ ? じゃあ、今まではどうして例外を用いなかったの ? 」 「 C + + の場合、例外が発生したあと、 stack の「 ewinding ( 巻き戻し ) が発生します」 「ええと、こういうことか ( リスト 12 ) ? 」 V リスト 1 2 C + + の stack の rewind void g() ひなた先生が教え 日臼 t ry { f ( ) } c a t c h ( . vo i d f ( ) Hoge hoge; throw null; 「この場合、関数 f で例外が発生すると、関数 f 内の stack 上に配置されているオブ ジェクト ( ここでは hoge ) のデストラクタを呼び出して、関数 g の catch で例外が 捕捉されると」 「はい。例外が catch されるまで stack 上のオブジェクトを次々に解体していく必要があ ります。そのことを stack の rewinding と呼びました」 「 C # だと、そういうコストはないのか ? 」 「はい。 GC ()a 「 bage Collector) がどこからも参照されなくなったオブジェク トを自動的に回収してくれますから、例外発生時に stack の rewinding を行う必要 はありません。ですので、 C + + で例外が発生した場合よりは、はるかに小さいオー バーヘッドで済みます。このため、 C + + よりは気軽に例外を使えます」 252