参照整合性(外部キー)制約 使う?使わない?

データベースエンジンには参照整合性制約機能が備わっているものがあります。

参照整合性制約を得意先マスタと売上伝票の例で説明すると、得意先マスタに登録していない得意先コードを売上伝票に登録しようとしてもできない、売上伝票に登録している得意先を更新・削除しようとしてもできないなどの制約をデータベースがチェックしてくれるのです。これによってマスタにない得意先コードが売上伝票に存在しない、言い換えると不正なコードを持つレコード(迷子レコード)が存在しないことが保証されます。

これを使うかどうかは時々議論になるようです。制約必要派の言い分はアプリケーションのチェックが楽になる、アプリケーションを介さずにデータを操作したときにも制約が保証される。不要派の言い分は大量の更新・削除処理で負荷が掛かる。開発時の変更が不自由である。アプリケーションでチェックすれば問題がないといったことです。

私は参照整合性制約を積極的に利用しています。

最近の開発案件では、ほとんどが新規開発ではなくてシステムのリプレースであることが多いのですが、従前のシステムに登録されたデータを見ると大抵の場合に迷子レコードが存在しています。

制約不要派は、UI上登録するときにマスタの一覧の中から選ばせるなどの方法で事前チェックが入るからデータベースの制約は2重チェックだという意見があります。これには落とし穴があります。ユーザがコードを選択してからレコードが登録されるまでの間には時間がありますのでこの間に他の端末で今選んだマスタのレコードが更新・削除される可能性に配慮しなければなりません。この場合にも迷子レコードが発生しないようにするには登録の直前にもう一度マスタを確認しなければならなくなります。マスタ確認の前にトランザクションを開始し、ライトロックしてマスタを読み、その後伝票を更新、コミットするという手順を踏まなければいけないわけです。

このような面倒な手間を考えるくらいだったら参照整合性制約に頼ったほうがよいと私は判断しました。

参照整合性制約を使った場合、コード変更はたやすくできなくなります。そのため連鎖更新の機能を使用します。連鎖更新ではマスタを変更すると伝票の方もコードが変更されます。また、使用頻度は多くありませんが連鎖削除という機能もあります。

連鎖更新・連鎖削除は便利な機能ではありますがデータベースエンジンの制限に気をつけなければなりません。Microsoft SQL Server2000では制限がきつく、例えば売上伝票に得意先コードと納品先コードがあり、そのどちらも取引先マスタを参照していると、売上伝票と取引先マスタの間に2つの参照整合性制約をつけることになるのですが、連鎖更新をこの2つの制約に付加することができません。連鎖更新をあきらめるかデータベーストリガで連鎖更新をエミュレートすることになります。意外にもMDBやオープンソースのPostgreSQLにはこのような制限がありません。

デザインパターン 装置制御への応用

とある検査装置を制御するプログラムをてがけました.。開発ツールはBorland C++ です。

この検査装置ではステージや測定器等のデバイスを、パラレルIO、シリアルIOで制御する必要がありました。また、待機中・測定中・復帰中などの状態管理が必要でした。

さまざまなインタフェースの入力を監視してそれに応じた動作を行なわなければいけないので、これをすっきり記述するため、Observerパターンを使用しました。大まかには、別スレッドで定期的にポーリングを行なうクラス→各種入力を監視するクラス(I/O毎にクラス作成)→状態を管理するクラス→画面表示クラスといった具合に連鎖的にイベントを起こすのです。クラス間の誘導可能性(クラス図に記述する矢印)はちょうどこれと反対の向きになります。

具体的な記述方法で工夫した点はObserver役にクラスではなくクロージャを使用したこと、Observer役の管理に標準テンプレートライブラリのvectorを使用したことです。クロージャを使用することで必要なクラスの数が減ります。vectorを使うことでTListを使うよりも型安全になります。VBや.NETではイベントの機構を使用すればObserver役の管理をランタイムルーチンがやってくれるのでもっとすっきりと記述できます(VBに関しては他の面でできないことも多いですが)。

Observerパターンを全面的に使用することで無駄なポーリングを回避でき、クラス間の関係がすっきりと記述でき、インターフェース毎のクラスの独立性が高いため入出力インタフェースの追加・変更も簡単になりました。

状態の管理はStateパターンを使用しないでswitch caseで判別しました。Stateパターンは状態1つにクラス1つ必要でクラス内のメソッド数が2個と少なくデメリットのほうが上回っていたからです。この部分のデバッグは非常に煩雑でわかり難く問題点として残りました。状態の管理はFiber(マイクロスレッド)や排他処理+通常のスレッドを使ったほうがよいかもわかりません。その場合異常状態をどのように表現するかがポイントなるものと考えています。

型総称性

オブジェクト指向に基づくプログラミングでは数多くのクラスを扱います。これらのクラスは個々のさまざま処理を実現するために必要となってくるものです。一方、さまざまなクラスに対して同じような処理を行いたい場合があります。リスト・スタック・キューなどは、殆どのクラスのオブジェクトがこれらの処理対象になりえます。

例えばリスト処理をDelphiで実現したければ、大元のクラスTObjectに対してリスト処理するクラスTObjectListを定義しておけば、継承による多態性が利用できるので、すべてのクラスに対してリストが使えるようになります。ここで特定のクラスTMyObjectについてリスト処理する必要があったとします。その場合にもTObjectListをそのまま使うことができますがTOjectListはTMyObject以外のものも扱える点が問題になります。例えば別のクラスTOtherObjectのオブジェクトを誤ってリストに加え、TMyObjectのつもりで取り出すと実行時エラーになります。できればコンパイル時にチェックしたいものです。

そこで、一つの解決策としては改めてTMyObjectのみを扱うクラスTMyObjectListを定義することが考えられます。しかしこれではクラスごとにリスト処理するクラスを定義しなければならず、単にタイプセーフにするためだけの代償としては大きいと感じます。

タイプセーフを保持しながらリスト処理の記述を一回限りで済ませたい。そういった要望に答えるのが型総称性です。古くはAdaのGenericにもありますが、C++ではテンプレート、JavaではJava
Genericがこれに相当します。

オブジェクト指向ではない言語Adaにもあることからもわかるように、型総称性はオブジェクト指向とは異なるパラダイムです。しかしオブジェクト指向で発生する多くのクラスを型総称性で統一的に扱えるという位置づけをするとこの2つは車の両輪となって働くものです。今後型総称性は台頭してくると考えられます。

キーワード:型総称性テンプレートJava genericパラメタライズドクラス

VB.NET vs Delphi

当方では普段はAccessを開発ツールとして使用しています。今回パッケージの開発を計画しており、開発ツールをどれにするか選定する中でVB.NETとDelphi 6を比較検討してみました。

VB.NETとDelphi比較
項目 備考
オブジェクト指向

どちらも、継承などの基本的な機能は揃っている。VB.NETにはデリゲート・マルチキャストイベント・ガーベジコレクタがある。Delphiにはクラス参照型がある. VB.NETは後発だけあって軍配が上がる。

ライブラリの配布

DelphiではVCLをスタティックリンクして単一実行ファイルにすることができる。それに対しVB.NETでは.NET FrameworkがダイナミックリンクとなりExe以外にDLLの配布に配慮しなければならない。.NET FrameworkはSide by Sideで配布できないためDLL HELLに注意が必要。

ライブラリソース Delphi Professional以上を購入するとVCLソースが付属する。ツール類の開発ではライブラリのソースに助けられることが多い。VB.NETにはソースが付属しない。

現在では主に C#, PHP を使用しています(2024/2/17)。

イノベーションを起こさないソフトウェア

当方は普段受託開発をしていますが、2002年3月には受託ではなくSI様常駐で生産管理システムTPiCSの外付けシステムのプログラム作成に携わりました。

このパッケージは資材所要量計算(MRP)に改良を加えたf-MRPの機能を持っています。TPiCS導入の動機は短納期化・在庫削減など経営レベルのメリットの追求にあると思います。システムに関連する部署も営業・生産計画・生産部門など広範囲に渡り、システム導入にはこれらの部署の連携が欠かせません。

ひるがえって当方が普段受注しているシステムはどちらかと言えば現場レベルのメリットを追求するものが多いです。色々なお客様に導入させていただいていると、仕事が半分に減った(効率が2倍になった)と喜んでいただいている事例もあり、お客様の業態に合わせてシステムを提案し構築することが効果をもたらすことを実感しています。

「業務をソフトウェアにあわせる」と言われることがあります。パッケージの特性を生かして経営的なメリットを出すと言う意味ではそのとおりなのですが、このことがパッケージを「ノンカスタマイズで導入すべし」ということに即つながるわけではないと思います。当方のような導入経験をしていると現場レベルのメリットを切り捨てると無視できない損失を生むであろうことが想像できます。経営のイノベーションを起こさないソフトウェアもそれなりに重要です。

TPiCSの導入ではパッケージで経営メリットを追求し、外付けシステムで現場メリットあるいは現場の損失カバーを追求するのがよりよいかたちではないでしょうか。

C++

久しぶりにC言語による開発をしました。といっても前回の開発はソフトハウスとしてではないので、開業以来初めてということになります。

C++は言語仕様が古臭いと思っていましたが、私の知らない間に少し改善されていたようで、テンプレートやネームスペースの機能が追加されていました。例外処理はtry
catchが導入されており、例外のために冗長なコーディングをしなくて済むようになっています。

今回は生産設備に使用するソフトをチーム開発し、私はDLLのコーディングを担当しているのですが、システム設計的には関数インタフェースとなっていてC言語の域を出ていません。オブジェクトインタフェースとすることでライブラリ化しやすいのでしょうが、緻密な設計とメンバーのスキルが要求されるため、なかなか採用できないのかもわかりません。

C++に関して興味を引いたのは標準テンプレートライブラリ(STL)と呼ばれるもので、デザインパターンにつながるものがあり、これを学習しようと考えています。

デザインパターン

クラスモジュールの活用を進めると汎用的なライブラリを作ることができるようになる反面、どのようなクラスを作って、クラスとクラスの関係をどうするかが難しくなってきます。当方もいろいろと試行錯誤しました。

最近、目にするデザインパターンはクラス設計を容易にするものではと思い、AccessのVBAに適用してみました。デザインパターンの解説書でよく見かけるのはJava言語を使ったもので、これをVBAに活用できるのかと不安がありましたが、今の感触としては十分役に立つものと認識しています。

私が学習に使った書籍はJava言語で学ぶデザインパターン入門(結城浩著)です。余談ですが、この書籍にあるデザインパターンをDelphiで書き直すと、Class参照型を活用することにより、書籍のJava言語による例以上にすっきりとデザインパターンを表現することができました。

デザインパターンについてはAccess 2000 VBAによるクラスモジュール活用の応用編としてVisual Basic Magazine2002年5月号に投稿させていただきました。コマンドパターンを中心にVBAで利用しやすいパターンを解説しています。

Linux

当方事務所にはLinux環境を揃えて、今後増えるであろうLinuxサーバを利用したアプリケーション構築に備えています。現在のところ2件のWebアプリケーション開発でLinux環境が役に立ちました。

先日、Linuxサーバ上でPostgreSQLを使用したWebアプリケーションをSI様に提案しました。しかしながらバックアップ・セキュリティチェックなどサーバの運用管理をどうするかといった問題を解決するためレンタルサーバを探してみたのですが、なかなかぴったりのものがなかったり、割高であったりしました。

そのなかでAKIRAというプロバイダの運営しているレンタルサーバは、共用サーバであるものの、2001年7月時点で最新バージョンであるPostgreSQL7.1.2をサポートしている上、リブートの依頼ができ、Perlモジュールもインストールしていただけるので開発時にも便利そうです。共用サーバであるがゆえに日々のバックアップ・セキュリティチェックがついています。費用も大変安く月額7,900円で500MByteの容量を確保できます。現在は募集していません。(2015/05/13追記)

今後、高速通信が普及すると事務所内で使用するクライアント/サーバシステムでさえ、このような安価なレンタルサーバを利用するソリューションを提案できる道が開けそうな気がします。

現在は事情が大きく変わり、大手レンタルサーバが安価なVPSを用意しています。(2015/05/13)

COM(ActiveX)について

COM(ActiveX)は基本的にはバイナリ標準で動的リンクの仕方を定めたものと解釈しておりますが、シンプルな機構でいろいろなものに応用されている点が面白いと思います。

表示形態による分類
表示形態 説  明
ActiveX DLL 画面表示しない、オブジェクト指向のDLLとして使える DAO,ADOなど
ActiveX コントロール フォームに貼り付けて使用する MSCommなど
ActiveX ドキュメント アプリケーションユーザがドキュメントを貼り付けて使用する Word文書中にExcelの表を貼り付ける場合など
実行形態による分類
実行形態 説  明
インプロセスサーバ 同一プロセスで実行する DAOなど
ローカルサーバ 同じマシンの別のプロセスで実行する VBからExcelをOLEサーバとして呼び出した場合など
リモートサーバ(DCOM) 他のマシンでプログラムを実行できる 分散アプリケーション

Accessバグ情報

Access97のバグやオンラインヘルプの間違い情報です。右端はマイクロソフトの回答です。
現象 対応等
同名のレポートをデザインビューで開くとフォームビューのフォームが閉じる 対応策なし
Option Compare Binaryで漢字がユニコード順で大小比較される、ヘルプではシフトJISとなっている ヘルプの間違い
Option Compare DatabaseでLike演算子の文字範囲指定に漢字を指定した場合、比較順序が比較演算子と異なりユニコード順になる 対応策なし
KeyPressイベントでKeyAscii=0としてもFEPの入力をキャンセルできない 次期バージョンで対応
Err.Raise vbObjectError+1050とすると、1050番のエラーが発生するとヘルプには書いてあるが実際にはvbObjectError+1050のエラーが発生する ヘルプの間違い
VB5も同様
Err.Raise vbObjectError+513で、96番のエラーが発生する。この番号はVB5のオンラインヘルプで指示している番号であり、このバグのためにActiveXのエラー処理が正常に働かない可能性もある。 対応策なし
Commitで引数にdbFlushOSCacheWritesを指定するとエラーになる dbForceOSFlushの間違い