上へ

開発メモ 2001/06

2001/06/10 PASCAL仕様書作成
機能別インデックスみたいなものが欲しいと漠然と思っていたものが、個人的に必要になったので実装。 頭が perl になっていないのと、 そのうち PASCAL仕様書作成に代わるもの(*)を作ろうと考えているので、書いたコードはメタメタ(^^; かなりの確率でバグがあるのではないかと(^^;;
(*)Delphi クラス図作成(仮称)
2001/05/27 日経ソフトウェア
「Kylix日本語版がやってきた」の表紙につられて日経ソフトウェアを買ってみました。 そのなかで「これがプログラミングの”新常識”だ!」という特集をやっていて、
第一部:カプセル化からデザイン・パターンまで
第二部:これからは「フレームワーク志向」でいこう
第三部:ライトな開発手法を身に付けよう!XP(Extreme Programming)
というタイトルで、とっかかりとして薦められそうかな、と思い詳しく見てみました。
カプセル化、継承のいまいち怪しい解説記事の後、デザインパターンを例を示して解説してあって、

■デザインパターン:(Template Method パターンの例)
>三角形と長方形の面積計算では、いずれも底辺と高さを用いるので基本的なパラメータは同じです。
>また、底辺と高さに値を設定するメソッドも共通化できそうです。
>このような場合に、Template Method パターンを使います。
(日経ソフトウェア2001/7月号特集記事より)
・・・う〜ん。なんか違うような気がする?GoF を引っ張り出して調べてみると、
|Template Method:1つのオペレーションにアルゴリズムのスケルトンを定義しておき、
|その中のいくつかのステップについては、サブクラスでの定義に任せる。(GoFより)
・・・ぜんぜん違うぞ。(^^;

この場合、Template Method を使うとしたら、
abstract class polygon {
  public void getMenseki() {
    algo();             // 仮想関数呼び出し
  }
  abstract protected double algo() {
}

class triangle extends polygon {
  public double algo() {                        // どうでもいいけどなんで public?
    ...
  }
}

class rectangle extends polygon {
  ...
}
ではなくて

abstract class polygon {
  public void getMenseki() {
    step1();    // step1 〜 4までのアルゴリズムのスケルトンがテンプレート
    step2();    //
    algo();             //  このステップだけサブクラス(triangle, rectange)での定義にまかせる
    step3();    //
    step4();    //
  }
}

だと思うけど、例に無理があるし、それ以前にポリゴンを継承して三角形や長方形を作る
継承構造自体にものすごく違和感がある。
・・・処理の高速化のため、三角ポリゴンや、長方形ポリゴンを特別扱いするのはあるかも
しれないので、多分、ポリゴンのフィールドが底辺と高さで、名前と実装がかけ離れているのが
違和感の元凶だと思う。

■デザインパターン:(Decorator パターンの例)
>Template Method パターンで実現した三角形の面積計算処理を、今度は Decorator パターンで
>実装したものです。ポイントは、抽象クラス polygon と三角形クラス triangle の間に手続きを
>装飾する decorate のための抽象クラス decorator を作ったことです。
>triangle クラスは decorator クラスを継承しています。さらに polygon クラスを継承した
>conpolygon も作成します。(日経ソフトウェア2001/7月号特集記事より)
・・・違うと思う。

+----------+       +--------+
|conpolygon|----|>|polygon |←-----+
+----------+       +--------+       |
|algo()    |       |algo()  |       |
+----------+       +--------+       |
                       △           |
                       |           |
                   +---------+      |
                   |decorator|------+
                   +---------+
                   |algo()   |
                   +---------+
                       △
                       |
               +-------+-------+
               |                |
          +--------+       +---------+
          |triangle|       |rectangle|
          +--------+       +---------+
          |algo()  |       |algo()   |
          +--------+       +---------+

class triangle extends decorator {
  public double algo() {
    Menseki = (x * y) / 2;
    return Menseki;
  }
}

クラス図の形はたしかに Decorator パターンになってるけど、肝心のコードがデコレート
してない。(^^;
この場合、無理やり Decorator パターンを使うとすればデコレートするために
triangle や rectangle の algo() では親クラスの algo() を呼ぶ
のでこんな感じになると思うけど。

class triangle extends decorator {
  public double algo() {
    super.algo();
    Menseki += (x * y) / 2;
    return Menseki;
  }
}

それ以前に、完全に意味の無い例になっているので、
縁取とか、穴あき、デコレータークラスを作って、穴あき三角、縁取り三角、穴あき長方形、
穴あき縁取りつき三角、穴2つあき三角、・・・が作れる例を示した方が良かったと思う。
この場合、conpolygon の位置に triangle と rectangle を置いて、triangle や rectangle
があった位置に縁取りデコレータや穴あきデコレータを置くことになる。

■これからは「フレームワーク志向」でいこう
>ここでは、その移行先となる、OSを仮想化してアプリケーション実行環境を提供する
>新しいプラットフォーム(Java や .NET)を「フレームワーク」と呼ぶことにしましょう。
(日経ソフトウェア2001/7月号特集記事より)

オブジェクト指向、デザインパターンと来た場合のフレームワークといえば、ひな型のことだと

思っていたんだけど・・・Java や .NETってそういう呼び方もあるのか?
結論として、作者的には人に薦められるような出来の特集記事ではなかった。残念。
2001/05/21 不健康肥満?
忙しい。電気図面を書いているんだけど最後に図面を引いたのは DOS の OrCAD の頃、 NEC PC-9801DA だったから。もともと無い予備知識が完全にクリアされていて、 線1本引くのに調べないといけないことが多すぎてもう大変。
忙しい・・・というより正確には遅々として進まず(爆)。
あと1週間の辛抱と思いつながら気が付けばもうすぐ1ヶ月。いまだに楽になる気配は無し。
・・・それは良いとして・・・太った。う〜ん、不健康肥満?
2001/05/08 keep-alive
InputForms・・・ヒストリ機能追加予定
TextPrinter・・・リサイズ位置ズレバグ修正、.DFM のサンプルを追加予定
CalcGrid・・・書式設定を Delphi コードで出力機能追加予定
心残りはあるんだけど、作者が結構消耗しているので、しばらく保留。
2001/05/01 仕事(その5 完了)
軸制御ボードのテスト、無いはずの IN1 信号線でパルス出力が停止しているので、 IN1 信号線を無視するコマンドを送ってドライブコマンドを送るとパルスが出てきた。 これでドライバアンプに接続すればモータが動かせるはずだけど・・・どの圧着工具を使えばいいのやら・・・(^^;
ボード上チップのレジスタの読み書きが正常にできていることが確認できたので、今後 OS を変えたことによるトラブルは考えられないし、 ボード自体は古くからあって枯れていると見なせるのでやることは完了。
CR フィルタが必要というのはチップの仕様書で、ボードには CR フィルタが載っていたし、 リミットスイッチは設定で断線検出ができるようにもできた。 休み明けにこの軸制御ボードで手配をかけることにする。 (手元にあるのは動作確認用の貸し出しボード)
2001/04/30 仕事(その4)
モジュールの組込み成功、デバイスビジーエラー状況から変わったのはカーネルと、 /usr/include に grep をかけてプロトタイプをちゃんと取り込んだのと、 作業者の頭が冷えた程度だけど、追求はまぁいいか(^^;
軸制御ボードのテスト、 汎用出力でさらに試す。状況がつかめてきた。コマンドに応答して電圧不定と、0Vが切り替わる・・・ 改めて仕様書を見ると汎用出力はバッファ出力だった。バッファ出力を開放したまま見たら そうなるわな(^^;<恥
これで軸制御ボードは I/O ポートを分割して占有しているけど、どうやら後半のポートを使っている ことが分かった。次はパルス出力をさせてみる。 I/O ポート監視ツールを作ってドライブコマンドを送ってみると、ドライブコマンドを送った タイミングでステータスの変化が起こっている。 仕様書と見比べてみると、パルスの出力停止状態で、停止原因は IN0 信号線。
IN0 信号線は・・・う〜ん、このボードでは基板スペース上廃止しましたって書かれているけど?(^^;
まぁいいや、つじつまがあってきた。不安だったアドレスの重複もなさそうだし、I/O ポート分割占有状態でも、ちゃんとレジスタの読み書きが出来ている。もう少しだ。
(ボード自体は古くからあるし、チップメーカのボードなのでボード自体の心配はしていない)
2001/04/28 続々仕事
実験マシンの復旧、手持ちの SCSI CD-ROM を接続して Linux のアップデートインストールを したところあっさり成功、1日がかりの覚悟を決めていたんだけど(^^;
日程上、手っ取り早くアップデートで復旧したが、今後、環境がままならない出先の作業を考えると、 ディスクレス構成を含めて、復旧方法、インストール方法はもう少しバリエーションを用意しておいた 方が良さそうだ。

残った時間で軸制御ボードをテスト。モータ、とドライバアンプは用意してあるけど、 仕様書を一目見て結線しただけで動くとは思っていないので、とりあえず CW+,CW- 間をオシロで観察することにする。
サンプル接続図を見るとリミット接続しなくてもパルス出力するようだけど、本当だろうか? リミット接続なし、リミット接続あり(Active High)、リミット接続あり(Active Low) の3通りをためすことになりそうな気もする。

cat /proc/pci を見ると、I/O ポートを分割して占有している。どっちがベースアドレスだろう? pcibios 系の関数でベースアドレスを取得したいが、pcibios 系の関数はドライバ中でしかつかえない ようだし、ドライバは insmod でエラーになるし、どうしようか。
一通りありそうなパターンで I/O ポートをたたいてみたけど、何の変化も無し。
CW+,CW- は動作前提条件が多いので、汎用出力ポートを観察することにする。
一通りありそうなパターンで I/O ポートをたたいてみた。ちょっと変わったけど、再現しない。
I/O ポート動作確認プログラムを作って、出直したほうが良さそうだ。

さらに仕様書を見ていくと、配線が長い場合はリミット接続で CR フィルタを入れたほうが良いという 記述が・・・、こういう記述がある場合、配線が短くてもやっぱりトラブって最終的には入れるはめに なるというパターンが多いんだけど、スペース上 CR フィルタは入れられないぞ?どうしよう?
2001/04/27 続仕事
カーネル構築中 make zImage で System too big とかいって怒られている。 make bzImage でやれば良いらしいが、とりあえずバックアップカーネルでは起動するし、 カーネル構成を削ってみる。・・・さらに削ってみる・・・さらに削ってみる・・・まだ大きい。思いっきり削ってみる。
コンパイル成功、再起動してみる ・・・カーネルロード直後くらいに kernel panic... 削りすぎたらしい、バックアップカーネルで起動してみる。 ・・・root をマウントする段階で kernel panic... 最後に勢いにまかせてモジュールまで削ってしまったのが悪かったらしい。 このマシン、フロッピードライブも CD-ROM ドライブもないし、完全にはまっている。 一度頭を冷やさないともっとなにか問題を起こすパターンだ。 さて、どうしよ。
2001/04/26 仕事
D/A ボードと、軸制御ボードが届いた。 cat /proc/pci で D/A ボードのベースアドレスを取得して、root 権限で I/O ポートを たたいてみたところ、あっさり動作。とりあえず保険が出来たので安心
ドライバーを作ってみた。insmod 時の unresolved reference はコンパイルオプションでクリア、 次は insmod で デバイスビジー となる、ソースを削りまくって init_module, cleanup_module のみで再現することを確認、lsmod を見ても2重登録というわけでもなさそうだし、なんだろ。 いろいろやっているうちに kernel 構築で失敗、バックアップカーネル起動状態に。
2001/04/22 TCalcGrid
他のグリッドへの参照が出来るように変更。 参照グリッドを取得するコールバック関数を増やすほうが正解だったようだ。 参照を戻すタイミングが自信がないけど、テストしてみた範囲ではうまくいってそう。
2001/04/20 仕事の話
作者のいる部署では画像処理のある設備開発の仕事をよくしていて、 相性問題でいろいろ痛い目を見ながらも、昨年ようやく Windows NT4.0 + Matrox MeteorII + α 構成で問題が起こらず 開発できる環境が出来上がりました。
ところが、最近 Windows NT4.0 + Matrox MeteorII の供給元から Windows NT4.0 構成の PC が近々入手不可能になると連絡がありました。
そのとき新規設備開発の検討をしていたのですが、 以前から Windows XP で設備開発をするはめになる前に 別の選択肢を用意しておきたいと考えていたことや、 今回の設備内容、共同開発者(CGI倶楽部管理人ぴか氏) 等から滅多に無いチャンスと考えて、今回は Linux 構成の方針で行くことにしました。 (本当は趣味に走った(^^;)
PC選定から、軸制御、D/A、画像各種ボードとも実績のないものを使うしかないので、 問題が起こったら引くしかないけど、どうなるだろう。
2001/04/15 InputForms
選択された文字列や数値自体を返す関数を追加。 継承構造の失敗から行数/機能が発散気味だったので書き直す。 相当手を加えたので、なにかあれば連絡を。(たぶんなにかある)
他にグリッドの行、列を Delphi 形式の 列、行形式にあわせる。
当初予定していたファンクションは揃ったので、後はヒストリ機能を付ければ終わりかな・・・。
2001/04/14 TCalcGrid, tcalc.txc, tcalc.dll
tcalc.txc WZマクロ側をコールバックにすれば tcalc.dll で内部メモリを確保する必要もな くなるので検討してみた。
・・・どうも引数が 4 つのものしかコールバックされないようだ。 コールバックしたい関数は引数 3つ(12byte)なのでコールバックされない。
WZ 専用の DLL ではないのでダミーの引数を入れるのも嫌だし、 いっそのこと "=Grid1!A1" とか他のグリッドへの参照も出来るようにして、 引数を 4 つにしてしまおうか
・・・調べ中・・・
TCalcGrid側
"Grid1" から実際のオブジェクトを見つける方法は柔軟性と拡張性の点から TCalcGrid 各オブジェクトに参照を登録することにする。 FindComponent や共用変数を使う方法は却下した。
DLL側
parser 擬似再帰呼び出し用のスタックまで変更が及ぶ、 字句解析、構文解析の他、push_range, pop_range, get_cell_value, その他周辺を書き換えれば意外に簡単に出来そうな気もするが、 方針を誤ると泥沼にはまる場所なので気が向くまで保留する。
・・・構文解析部を眺めていたら、他のグリッドへの参照を入れたとしても コールバックの引数は増やさないで、参照グリッドを取得するコールバック 関数を追加する方が正解のような気がしてきた。
いずれにしても保留する。
2001/04/12 TCalcGrid
GridEdit でメモリリーク現象の起こる Windows2000 環境を1時間ほど貸してもらいデバッグ (桑原さん感謝)
DLL のロード、アンロードだけで起こるらしいところまで絞り込めた。 DLL 内部メモリの確保、開放条件を DLL_PROCESS_ATACH, DLL_PROCESS_DETACH に変更してみる。
2001/04/11 TCalcGrid
GridEdit.exe が Windows2000 環境では立ち上げて終了するだけで落ちるらしい。
TCalcGrid のインスタンスが開放される時に、参照しているグリッドが存在してないのかも。 FreeNotification で参照先の開放のタイミングで参照を解除させてみた。
作者環境(Windows95, Me)では再現しないので分からないけど、多分直ったのでは・・・。