個人的な経験では,このようなエラーには「削除する」処理が絡んでいる場合が非常に多いです。
ですから,ある機能を設計・実装している場合に,「このデータが削除される時に,残りのデータが正しくあるためには,現在の仕様・処理・操作手順で本当に大丈夫か?」を考慮すると,後々のテスト段階で非常に助かります。
ここで重要なのは,「このデータは削除されないから,あんまり考えなくていいや。」と考えては絶対にいけません。なぜかというと「仕様は変わる」からです。
少なくとも,私の働いている部署の場合は,仕様と納期は必ず悪いほうに変わります。
餅は餅屋 デバッグはデバッグモード
Visual C++では,ビルドの時に「Debug ビルド」と「Release
ビルド」を選択できるようになっています。
Visual Basicでも,Ver.4以降では,コンパイル定数をサポートしますので,同様の手法を取ることができます。
MFCやVBのランタイムは,DebugとReleaseでとんでもなくサイズが違いますが,これは「Debug時だけ組み込まれる自己診断用のコードが大量に入っている」からです。
例えば,
とはいうものの,私がよくやってしまうミスに,整合性をチェックする方式がバグっているために,「正常に動作をしたときだけ警告される」ようなコードを入れてしまう場合があります。みなさんも気をつけましょう。
そしてこういった自己診断チェック用コード部分は,リリースモード時のコンパイルではコンパイル対象にならないようにしておくと,自己診断によるパフォーマンスの劣化やサイズ増大は無視できるようになります。
自分の身は自分で守れ
これはどういうことかというと,「パラメータとしては有効だが,処理上は問題があるパラメータ」で呼び出された場合にも,できるだけエラーで戻るようにするということです。
Window95やNT上での場合,ひどい場合には悪名高い一般保護違反すら検出して,リカバリー処理を行うことが可能です。
よくあるパターンとしては,
あるプロジェクトで過去に私が手がけたモジュールには,エラーコードとして,「アドレス違反」を用意してました。あらかじめ,指定された領域に対して実際に書き込みが可能かどうか試し書きをしてみて,その時点で失敗したらこのエラーで呼び出し元に戻るようにしていました。
ただしこの手のエラーは,大本の原因は呼び出し元にあることが多いので,やりすぎると,変に呼び出し元が正常なエラー処理をしてしまい,バグを見えにくくしてしまう事があります。そのプロジェクトの時もそのような場合がありました。何事も程々が肝心だと反省してます。
Tipsに戻る
インターフェースをあいまいにしない
別の言い方をすると,「結合テスト」でのテスト範囲になるような部分で,曖昧な部分を残さないということになります。具体的な例でいうと,
インターフェースをあいまいにする
上と言ってることが違うって? 確かに違います。違うからには違う理由があって,何が違うかというと仕様の確定とPGのタイミングが違うんです。
通常の場合は,仕様の確定のあとにPGが行われます。この限りにおいては,これから述べることは当てはまりません。
しかし,「仕様が全て確定していないが,確定している範囲でプログラムを書かなければいけない状態」になった場合には,「インターフェースをあいまいな形式にして,多少の変な仕様になった場合でも,インターフェースに投げるパラメータを調整することで対応」するようにできると効果的です。
これは,いわゆる「呼び出される側をコンパイルし直したら,呼び出し側もコンパイルし直さなければならない」状態を避けるようにするということです。
当然,確定したときに変更あるいは追加になった機能を,呼び出し側が必要としているなら,呼び出し側の変更は当然必要になるんですが,そうでない場合は,変更しないですむようにしておくと,呼び出し側の担当者から喜ばれます。
人のものは俺のもの 俺のものは人のもの
これは,「自分で書いたプログラムは,できるだけ人からも(さらに可能なら,その機能単体で)利用されることを考慮して書く」そして「既にあるものはわざわざ作らない」という事です。要は,総「共通ライブラリ化」ですな。
前半部分に関しては,利用されることを考慮して書くだけで終わってしまうと,もちろん余計にしんどいだけです。
しかし,ひとたび「ここの画面を共通化して…。」「ここのアクセスを共通化して…」となった場合は,状況は一変します。
あなたは,「これはここ,これはこのモジュールをリンクして,これとこれとこれを呼べばデータが取れるから,後はがんばって。」あるいは,「それは,このコントロールを張り付けて,そのプロパティを見たら選択されたやつがわかるから。」そう言ってあなたは家に帰ればいいんです。きっと,あなたが寝ている間も,その人は共通化する部分の切り出しと,それに伴うバグ退治で一生懸命になっていることでしょう。
もう一つ効果的な場合は,それぞれで同じ事を独自の方式でやっていて,それでは具合が悪いから,統合しようという話になった場合です。一般的に,利用されることを考慮してあるモジュールの方が,汎用性・拡張性が高いことが多いようです。当然の事ながら統合の際の労力が最小になる方式で統合することが大半だと思います。従って,「他からの移行が行いやすい方式」にしておくと,「自分のやっている方式に合わせてもらう(自分の担当分を変更しなくて済む)」可能性が高くなります。
後半部分については,これは私も良くやってしまうことなんですが,「既にあるやつを改めて作りなおす」事についてです。機能的に不足がある部分はもちろんしょうがないです。しかしその場合でも,できるなら「作り直し」たり「書き換え」たりしないで,「付け足す」方向では実現できないのかを考えてみてください。
大体にして,「作った」からには,動作テストをしなければいけません。既に誰かが作っていて,そこそこ動くやつがあるのに,わざわざ1から作ってしまったら,そこの部分のしんどいテストをするのは「あなた」です。バグの対処をするのも「あなた」です。
「付け足す」あとにバグが出ても,それが付け足した部分が原因でないのなら,バグの対応は,「付け足し元」がやってくれるじゃないですが!テスト項目のピックアップは,「付け足す」部分だけで,肝心の部分は,「付け足し元」がやってくれるじゃないですか。どうしてわざわざ「あなた」が苦労する必要がありますか? それにこのような場合,「元を作った人がした失敗」を,そのままあなたもしてしまう場合が多いようです。わざわざ人が先に失敗してくれていて,しかもそれに対する解決策もとってもらっているのに,あらためて「あなたが」失敗する必要どこにあるのでしょう?
人の書いたものの仕様を新しく覚えるのは大変そうに感じます。また,納期直前のような場合は,とりあえず作って対処する必要があるのも確かです。でもよく考えてください。仕様を把握する(覚える必要はありません。ヘルプでも何でも見ながらできればいいんです。)間に,あなたはいくつのバグを潰せますか?
マルチスレッドは便利!
システム開発が仮運用段階になると,パフォーマンス上の問題が発生してきます。
代表的な物には,ありとあらゆるところで使用される一覧表示を行う部分があります。
これはそもそも,テスト段階で少量のテストデータしか用意していない(=テスト期間が少ない)ということと,プログラム上でも,必要なところで大量のデータを処理する場合の考慮がされていない(というか,ほとんどの場合する余裕がないのでしょうが)事によります。
このような場合は,可能であればマルチスレッド化を行うと,特にあなたがユーザーインターフェース周りを手がけているのであれば,パフォーマンス上の問題について文句を言われる可能性は激減します。
一歩譲っても,1データ要素の処理毎に,ユーザーの中断操作などを受け付けられるようにできればより効果的です。
実際には100件0.5秒でデータを取ってくる必要がある場合でも,大抵の場合で欲しいデータが先頭20件以内にある場合なら20件0.5秒で処理できればよくなります。そしてこれは(データベースなどの性能を無視すれば),データ件数が1000件だろうと10000件だろうと,大抵の場合に0.5秒でユーザーに反応を返すことができるということです。体感上の速度を上げられるので,ごまかしができるんですね。
もちろんマルチスレッド化する場合は,同期処理の問題があり,この部分をどうするかが最大の課題ですが,それさえ適切に処理できれば問題はないのです。
新たに考慮しなければいけない点は,極論で言ってしまえば,サーバー上で共有しているファイルや,同一端末に複数のサブシステムが起動した場合と何ら変わることはないです。全てが共有メモリになってしまうというのはありますが,処理上の考慮という点では,実現方式こそ違え,マルチスレッド化したからといって,特別な注意は必要ないはずです。
それとも,あなたはそんないい加減な,複数の端末から何らかのタイミングで書き込みが競合した場合に動きがおかしくなるような,怪しい処理を今までずっとやっていたのですか?
3種の神器
私が所属してる部署の場合,少なくとも今までは,サブシステム単位で開発範囲を分割しています。そこから実際に開発していくのですが,サブシステムという単位では分割できない機能がいくつか出てきます。
大抵は,それらを集めて「共通ライブラリ」と称して開発を行いますが,いつも決まってそれらの中から漏れる機能があります。これは,次のような理由によります。
つまるところ,システムのアーキテクチャやポリシーの設計・伝達ができていない事から来ると(私は)思ってるんですが。
もちろん,実際にそのレベルからできるかというのはまた別の問題です。
でも,それができないならできないでいいから,できない事を前提としたスケジューリングなり機能範囲の決定をしてほしいし,そうでないスケジュールに沿ってできなかったことをSEやプログラマのせいにしないでほしいなぁ…
そのあたりのさじ加減をどうするかの決定と意志伝達は,完全にプロジェクトマネジメントレベルの話だと思うんですが。
例外のない規則はない
特にVisual Basicの場合は,組み込みの機能で発生するエラー処理はほとんど全て例外処理にされてしまいます。例外処理という名前に似合わず,例外処理は必ず必要です。
それがいやなら,Visual Basicは使わずに,Visual C++などの他の言語を使用しましょう。今まで通りに黙って怪しい処理を行ってくれます。
使用するファイルは必ず無い物として,接続先のデータベースや,その中のテーブルは必ず無い物として,渡されたメモリ領域は必ず確保されていない物として,渡されたコードは範囲外の値だということを心してください。
…とはいうものの,実際の所,私はとてもここまでできません。きりがないです。だから私はC(++)言語の方が好きなんですよ。運が良ければ例外を黙って見逃してくれますから。