タイソン・ギル著の「Visual Basic6 エラーコーディング」を土日で読破しました。
以前に「例外処理はどれがベストなのか?」というエントリーを書いた所、この本を紹介していただいて今回やっと読めました。
一回さらーと流して読んだ感想を書きますので、もしかしたら著者の言いたいことをちゃんとくみ取っていない可能性もあるので、それを考慮して続きを読んでください。
この本でだいぶ疑問に思ってたことが解消できたように思います。それと、基本的なことが徹底されていなかったなーと反省。
ただし、鵜呑みにしてはいかんし、ここに書かれている手法は完璧なものではないと思います(実際、この本にもそんな記述があったと思う)。
もともと2000年に書かれた本なので、今の風潮とか流行とかからすると違和感があったりします。今の仕組みと照らし合わせて取捨選択は必要だと思われます。
コーディングに関しては「プログラマのメモ帳」というサイトに「VBコーディング標準」というのがあるのですが、ここはこの本とはまた違う方向からコーディングについて記述されています。
例外の扱いに関しては、まるで逆の意見になっているので、混乱してしまうかもしれませんが、本をそのまま信じ込まずにいろんな手法を比較検討した方が良いと思います。
例えば、前者はエラーを戻り値でチェック(エラーは起こしてはならない!)、後者はエラーをErr.Raise(スロー)して呼び出し元のOn Error Gotoでキャッチすることで対処という方法になっています。前者の考えだと、クラスのプロパティーは使っちゃ駄目ってことになります。戻り値がエラーを表す値(“”とか-1とか。この本だとエラーを表す文字列)にならないと駄目なので。実際にこの本の中ではクラスのプロパティーは使わない方が良い、この場合はメソッドにすべきとなっています。
じゃあ、クラスのGetValue(name as string) As Stringなんて関数はどうすればいいんだというのが次に疑問にあがってきましたが、これに関しては謎が解けませんでした。この本の中には防御的なコーディングと言うことで、中でエラーが起きさせないでルーチンを抜けるようなコーディング例が挙がっています。戻り値は正常な場合はその文字列、エラーの場合は0バイト文字みたいな感じです。でも、実際に0バイトの文字が入ってるのか、それともエラーなのかを知りたい場面もあると思うのです。この場合もしエラーが起きていてもそのエラーは隠蔽されてしまってるわけですから、この本で言う悪い例の「エラーの抑制」になってしまうのではと思うのです。
まぁ、0バイト文字かエラーかを区別したいなら、GetValue(byref name as string) As Stringと書け、ということなんでしょうかね(でも、この本の中でByrefは推奨しないと書かれていますけどね)。
ただ、前者はシンプルだと書きましたけど、例外を受け取る方がスマートに書けないのがVB6なんですよね。Try Catchがないですから、インラインで処理するにはOn Error Resume Nextして、次の行でIf Err.Number <> 0 thenでエラーナンバーを調べないといけないのです。
Resume Nextは下手するとエラーを無視してしまうので使いたくないですよね。
On Error Goto xxxでエラールーチンにとばせば良いではないかと思う人もいるかもしれませんが、その関数内でエラーが起きそうなサブルーチンを複数読んでいた場合で、それぞれで対処法を変えたいときとかにちょっと面倒な感じじゃないですか?
まぁ、エラールーチンは複数定義できるので、
Public Sub Hoge
On Error Goto Ex1
Call RaiseException
On Error Goto Ex2
Call RaiseException2
Exit Sub
Ex1:
‘エラー処理1が書かれていると思いねぇ
Exit Sub
Ex2:
‘エラー処理2が書かれてるのさ
Resume Next
End Sub
うーん、こうすればいいのかなぁ。こんなんなるんだったら関数分けろってことかな?
まぁ細かい所で疑問は残りましたね。
さて、この本は割と実践向きの内容になっていると思います。VB6でやれる範囲で統一されたエラー処理コーディングを採用することで、コストをあまりかけずに確実なエラー処理を行うことを最優先し、そのためにはオブジェクト指向的に美しくなかったり(プロパティーを使わないとか)、イマイチな手法を使う(引数はすべてVariant)のは仕方がないというような感じで書かれているように思います。無理にオブジェクト指向的な考えや、Javaなどで一般的に使われている手法を採用せずにVB6なりのエラー対処の方法が書かれているといった感じです。
引数はすべてVariantなんてまさにVBらしい使い方です。
以前も少し書きましたが(例外処理はどれがベストなのか?)、VB6ってVariant推奨みたいな所があるので、これはVB6では便利かもしれません。
変数呼び出し側で毎回型変換やるのも確かに大変ですしね。
しかし、型変換のロジック分散という問題だけ考えると、.NETなんかだとオーバーロードを使うことにより解決するので、他の言語を使う人は、そのあたりを考えながら読むべきでしょう。
階層型アプリケーションはなかなか参考になりました。ユーザーインターフェースとビジネスロジックの分け方の考え方とかはなるほどと思いました。
エラー処理についてここまで書いてある本はあまり無いと思うので、機会があったら読むことをおすすめします。新人さんもベテランさんも勉強になると思いますよ。
(この人に.NETでのエラーコーディングの本を書いて欲しいな)
Amazonや楽天はなんかずっと品切れなので、すぐに欲しい人は出版社のピアソン・エデュケーションから直接買った方が早いかも。
以降、俺用メモ。
本読んだ人はわかるかも。
-例外を起こすな
-引数はすべてVariant(.netではオーバーロードを使うと良い?)
-SEM(安全なエラーメッセージ)も.netではInnerExepsionやStackTraceがあるので自作しなくても良い。
-プロパティをつかうなメソッドでよい。なんだか気持ち悪いが反論できん。
-プロパティはIDEなどで機械的に処理を行う(ActiveXやJavaBeans)ためのものという考えなのかも。
-エラーが起きない事を保証できる(=防御的コーディングがされている)ならプロパティーを使っても良い
-攻撃的(エラーが起こったことをなるべく早く通知する)と防御的(エラーを起こさないようにする。エラーなら””を返すとか)
-オブジェクト指向の考えとはマッチしない所もあるような
-今はそうしゃなくても将来変更される可能性を考えてエラー対策
-コードブロック単位での再利用(メソッド単位よりもさらに細かい単位)
-だいたいvariantなんか使うからlenにラッパー関数が必要になるんじゃ?という気も。
-つまりはvbの標準関数はエラーを出しすぎだと(Uboundとかね)
-.netでこのあたりの情報が見あたらないのは、これ(LENとかUBOUNDとか)より上流の行程が注目されているというだけなのかも。.netが低レベルな処理はうまく処理してくれてるというのもあるのかも。
-トップの影響。そりゃ、トップがさぼってたり、逃げ腰だったら下の者はうまいいいわけに使えるもんな。
-なにか助けはいるかいという姿勢は大事(協力的競争)
-個人的競争になるとドロドロしちゃうもんなぁ(欧米風のプライベートがなにより大事みたいな)
-安全が保証されるコードには特定の人しか触れない(XPとは違う考え方。XPはテストがあれば誰でも触って良しとする)