ヒューマンインタフェース’99 ＃ 2
久野靖∗

1999.4.16

はじめに

1.2

□ 穴埋め書式が画面に表示され、それを埋めて行く□ 前回は「インタフェースを設計してみる」ところまでで時間切れになってしまいました。

__________________________________□ 今回は「作って動かす」ところから始めて、その後で「計Command: _____

算機入力の人間学」ぽい話をしましょう。

GUI 以前の代表的なユーザインタフ
ェース方式

1

フォーム方式

Prod-ID: _____QTY:_______

Cust-ID: _____

Date: _________________________________________• 「何を打ち込むか」は覚えてなくてよい□ とりあえず、画面端末まででデータ入力などに使われていたものでいうと:• 「どのように打ち込むか」は覚える必要がある (しかし大抵は自明)• コマンド方式: コマンドやオペランドを 1 行ないし複数行で打ち込んで行く• 必要なら「どのように」の説明もフォームに含める• 書式 (フォーム) 方式:
目を記入し行く• メニュー方式:

ことができる

記入欄を持つ画面に必要項□ その他の特性:

メニューが表示され、その中から項• 欄によっては「あけたまま」にしておくこともある

目を選択して行く

1.1• 打ち込む位置の移動はタブなどのキー操作で行うのが普通

コマンド方式□ コマンド、オペランドを順に打ち込んで行く

1.3

メニュー方式□ 画面がメニューになっていて、そこから項目を選択する
Q> ship prod=QS190241 cust=15141 qty=50 date=4/30/99と次の画面へ進む• パラメタ、書き方などすべて覚えている必要がある__________________________________• その代り高速にできる (設計しだい)• エラー検出のワザが多数使用できる□ その他の特性:• 「位置パラメタ」と「キーワードパラメタ」がある。
• 現在ではコンプリーション (補完) のようなワザも使える。

Command:
1: Ship
2: Order3: Query Stock
9: EXIT__________________________________• 「どれか 1 つを選択するだけ」だから極めて簡単、何も覚えておく必要がない→初心者むけ• その時点で選択可能でない選択肢は始めから選べない• その代りのろい!
面→見る…

∗ 筑波大学大学院経営システム科学専攻

1

見る→考える→選択操作→次の画• 簡単に迷子になってしまう

2.2

演習

• 最後まで全部メニューには普通できない (データ入□ 上記のような条件で、 3 方式 (コマンド、フォーム、メ
力とか…)
ニュー) の入力アプリケーションを設計せよ。
• なのでフォームと組み合わせることが多い• 画面例を描くこと (画面をスケッチすることはよい□ その他の特性:設計の手段)• GUI の (マウスで選択する) メニューとはちょっと違 □ 自分/他人の設計を次の点から検討せよう (マウスだとさらに遅い)• その設計だとどのような入力間違いが発生するか• その設計だとどの部分で時間が掛かると思うか

設計演習

2

• その設計だと 1 項目あたりの入力時間はどれくらいだと思うか□ あるシステムのユーザインタフェースを上記の 3 方式で設計する□ シナリオ:□ 上記の検討で問題となった事柄を解消する手段を検討
せよ

専門のオペレータが使うインタフェース• 備わっている機能: 「発送処理」「補充注文」「在庫確認」「終了」• どの処理かの選択は行うが、実際には「発送処理」の□ ソースファイル:部分だけ実装する• 「発送処理」に必要な項目:「商品番号」「数量」「顧客番号」「発送日」

2.1

C コンパイラの使い方

3

すべて「XXXX.c」のように、最後に「.c」をつける。
□ 今回の例題は termcap ライブラリを使うので次のようにする。
% gcc file1.c file2.c file3.c -ltermcap
イル% ./a.out

データ例

←コンパ
←実行

□ データの例を示す (設計に当たって本物のデータを見る事は重要!)• 商品番号の例:
かれている)

4(入力伝票には番号と名前が両方書□ コマンド入力のためのライブラリルーチンを作ってみた。

0151 Steel Desk (Large)
0152 Steel Desk (Small)1044 Pine Table
1241 Pine Bench (Long)
2415 Pine Chair
5514 Old Fashoned Swing
4156 Color Pencil Set
0843 Convertible Sofa
5141 Magazine Rack

• 顧客番号の例:
かれている)

コマンド入力• cmdinput:

プロンプトを出し、1 行入力。入力した行の内容を空白で区切り、各かたまりを 1 つの文字列にして渡された配列に入れる。
ある文字列が別の文字列のプレフィク• cmdprefix:

スになっているかどうかを調べる。

• cmdrecog:(入力伝票には番号と名前が両方書ある文字列が指定した複数の語のどれのプレフィクスになっているかを調べる。

A0012 Jack Lennon
A1021 Loan Channon
A1581 Susan McDonald
B0141 Julian Garland
B1042 Suna Alford
A4015 Canon Hufford
B1411 Judy Barman
C4105 Lenox Bullis
B0015 Alenn Gummon

4.1

コード: command.c#include <stdlib.h>#include <stdio.h>#include <string.h>#include <ctype.h>#define MAXBUF 4096
cmdinput(char *msg, char *words[], int n) {static char buf[MAXBUF];
int c, i, j = 0, p = 0, l = 0;

2

4.3

char *s;printf("%s ", msg); fflush(stdout);
while((c = getchar()) != EOF && c != ’\n’) {if(l+2 < MAXBUF) buf[l++] = c;}buf[l++] = ’ ’;for(i = 0; i < l; ++i) {if(isspace(buf[i]) && p < i) {buf[i] = 0; c = strlen(buf+p); s = malloc(c+1);
strcpy(s, buf+p); if(j < n) words[j++] = s;p = i+1;} else if(isspace(buf[i])) {p = i+1;}}
return j;

演習□ 上記のライブラリを利用して先のデータ入力プログラムを作成してみよ。

画面端末の制御

5□ 画面端末:エスケープシーケンスで制御• あくまで最後に描いたものが残っている• プログラム内部:
と言いたい

}

「これこれの位置に文字を描く」□ 使いやすい界面と効率よい描き直しを実現するライブラ

cmdprefix(char *p, char *s) {int i;
for(i = 0; ; ++i) {if(p[i] == 0 || p[i] == ’=’) return i;if(p[i] != s[i]) return -1;}}

リを作ってみた

cmdrecog(char *cmd, char *words[], int n) {int p = 0, len = 0, i, k;for(i = 0; i < n; ++i) {int k = cmdprefix(cmd, words[i]);printf("(%s,%s,%d)\n", words[i],cmd,k);if(k < 0) {; /* do nothing */} else if(k > len) {len = k; p = i+1;
} else if(k == len) {p = -1;}}
return p;}• scrgetc:• 内部バッファに画面の写しを保持し、変更箇所のみを端末に送信• scrinit, scrend:

初期設定、後しまつ (端末の設定を変更)

1 文字入力• scrlines, scrcols:

画面の行数、カラム数を取得

画面を全クリア• scrclear:• scrputc, scrputs:

指定位置に文字/文字列を書

き込む• scrputl:

scrputs と同様だが行末までクリア• scrupdate:• scrpos:

5.1

変更内容を画面に反映

カーソルを指定位置に置く

コード: screen.c/* screen.c --- screen package, input handling */#include <stdio.h>
4.2 コード: t30.c — テストドライバ#include <termios.h>static char tibuf[1024];
static char *cmds[] = {"exit", "edit", "edu", "bye", "good"};static int **line;
static int **lineb;main() {static int co, li;char *w[100];
static struct termios ttb1, ttb2;
int i, l;#define HL 0x80000000
while(1) {while((l = cmdinput("Q>", w, 100)) == 0) ;/* scrinit -- initialize screen */for(i = 0; i < l; ++i) printf("%s\n", w[i]);scrinit() {i = cmdrecog(w[0], cmds, sizeof(cmds)/sizeof(char*)); int i;
printf("%d\n", i);if(tcgetattr(0, &ttb1) != 0) {if(i == 1) exit(0);fprintf(stderr, "cannot get termnal controls.\n");}exit(1); }}ttb2 = ttb1;
ttb2.c_iflag |= IGNBRK;
ttb2.c_iflag &= ~ICRNL&~ISTRIP&~IXOFF;
ttb2.c_oflag &= ~ONLCR;
ttb2.c_cflag |= CS8;
ttb2.c_cflag &= ~PARENB;

3

scrputc(l, c, ’ ’, 0); ++c; }ttb2.c_lflag |= TOSTOP;}
ttb2.c_lflag &= ~ISIG&~ICANON&~ECHO&~ECHOE&~ECHOK&~ECHONL&~ECHOCTL&~ECHOPRT;/* scrupdate -- update screen actually */for(i = 0; i < NCCS; ++i) ttb2.c_cc[i] = -1;
scrupdate() {ttb2.c_cc[VMIN] = 1;
int i, j, l, r, h = 0;
ttb2.c_cc[VTIME] = 0;
for(i = 1; i <= li; ++i) {if(tgetent(tibuf, "ansi") <= 0) {for(lfprintf(stderr, "cannot find terminfo entry.\n"); exit(1);} = 1; l <= co; ++l)if(line[i][l] != lineb[i][l]) break;li = tgetnum("li");for(r = co; r >= l; --r)co = tgetnum("co");if(line[i][r] != lineb[i][r]) break;line = (int**)malloc(sizeof(char*)*li+1);
if(l <= r) {lineb = (int**)malloc(sizeof(char*)*li+1);
printf("\033[%d;%dH", i, l);for(i = 1; i <= li; ++i) {for(j = l; j <= r; ++j) {line[i] = (int*)malloc(sizeof(int)*(co+1));
if(line[i][j]&HL) {lineb[i] = (int*)malloc(sizeof(int)*(co+1));
if(!h) { printf("\033[7m"); h = 1; } }}else {
scrclear();if(h) { printf("\033[0m"); h = 0; } }tcsetattr(0, TCSANOW, &ttb2);
putchar(line[i][j]&0x7f);}
lineb[i][j] = line[i][j];}/* scrend -- finalize screen */}scrend() {}tcsetattr(0, TCSADRAIN, &ttb1);
if(h) printf("\033[0m");}}/* scrgetc -- read 1 char from keyboard *//* scrpos -- position cursor */scrgetc() {scrpos(int l, int c) {char buf[1]; read(0, buf, 1); return buf[0];printf("\033[%d;%dH", l, c); fflush(stdout);}}/* scrlines -- return no. of lines */scrlines() { return li; }5.2/* scrcols -- return no. of columns */scrcols() { return co; }コード: t47c.c — 画面お絵描き/* t47c.c --- screen demo */#include <stdio.h>/* scrclear -- clear screen */scrclear() {int i, j;for(i = 1; i <= li; ++i) {for(j = 1; j <= co; ++j) line[i][j] = ’ ’;for(j = 1; j <= co; ++j) lineb[i][j] = ’ ’;}
printf("\033[2J"); fflush(stdout);}main() {int i, j, c, co, li;
int mode = 1; /* 1:draw, 2:erase, 0:pass */scrinit();co = scrcols();
li = scrlines();i = j = 10; scrpos(i, j);while((c = scrgetc()) != ’q’) {if(c == ’d’) mode = 1;/* scrputc -- put a charcter on the screen */if(c == ’e’) mode = 2;
scrputc(int l, int c, int x, int h) {if(c == ’p’) mode = 0;x &= 0x7f; if(h) x |= HL;if(c == ’h’) --j;if(1 <= l && l <= li && 1 <= c && c <= co) line[l][c] = x;if(c == ’j’) ++i;}if(c == ’k’) --i;if(c == ’l’) ++j;/* scrputs -- put a string on the screen */if(mode == 1)
scrputs(int l, int c, char *s, int h) {scrputc(i, j, ’*’, 0);
while(c <= co && *s) {else if(mode == 2)
scrputc(l, c, *s, h); ++c; ++s; }scrputc(i, j, ’ ’, 0);}scrupdate(); scrpos(i, j);}/* scrputl -- put a string on the screen */scrpos(li, 1); scrend();
scrputl(int l, int c, char *s, int h) {}while(c <= co && *s) {scrputc(l, c, *s, h); ++c; ++s; }while(c <= co) {46大きな単位での配置

layout_t *lay = layout_create(4);layout_sets(lay, 0, 2, 5, "aaaa");layout_sets(lay, 1, 4, 5, "bbbb");
layout_sets(lay, 2, 6, 5, "cccc");layout_sets(lay, 3, 8, 5, "dddd");
scrinit();li = scrlines();layout_update(lay);scrupdate(); scrpos(li, 1);
while((c = scrgetc()) != ’q’) {layout_toggle(lay, 2); layout_update(lay);scrupdate(); scrpos(li, 1);}
scrend();□ 任意の文字列を画面上の任意の場所に置くようにした。

• layout create:用意• layout sets:

N 個の「文字列」が置けるように

i 番目の「文字列」を設定/変更• layout toggle:
転をトグル

i 番目の「文字列」の反転/非反• layout update:

変更を画面上に反映}

6.1

コード: layout.c

typedef struct unit {int l, c, h; char *s; } unit_t;

7

フォーム機能□ レイアウト機能を利用すればフォームは簡単

typedef struct layout {int size;
unit_t *body; } layout_t;• formfill:layout_t *layout_create(int size) {layout_t *lay = (layout_t*)malloc(sizeof(layout_t));lay->size = size;lay->body = (unit_t*)malloc(sizeof(unit_t)*size);
return lay;}

フォームを表示し記入。渡す配列の奇数番目はタイトル、偶数番目は入力欄になっている(呼ぶ側で配列をそのように設定して呼ぶ)

7.1

コード: form.c

formfill(char *mes, char *form[], int n) {layout_sets(layout_t *lay, int n, int l, int c, char *s) {int sel = 0;
int li = scrlines();if(n >= 0 && n < lay->size) {lay->body[n].s = s;
int i, c;lay->body[n].l = l;char *s;scrclear();lay->body[n].c = c;lay->body[n].h = 0;
scrputs(1, 1, "[TAB]: next, [RET]: end", 0);}
scrputs(li, 1, mes);
while(1) {}for(i = 0; i < n; ++i) {layout_toggle(layout_t *lay, int n) {int h = (sel == i);
scrputs(i*2+3, 15-strlen(form[2*i]), form[2*i], h);if(n >= 0 && n < lay->size)lay->body[n].h = !lay->body[n].h;
scrputl(i*2+3, 17, form[2*i+1], h);}}scrupdate(); scrpos(li, 1); c = scrgetc();
layout_update(layout_t *lay) {s = form[2*sel+1];
int i;
if(isprint(c)) {i = strlen(s); s[i] = c; s[i+1] = 0; }for(i = 0; i < lay->size; ++i) {unit_t *u = &lay->body[i];else if(c == ’\b’ || c == ’\177’) {scrputl(u->l, u->c, u->s, u->h);i = strlen(s)-1; if(i >= 0) s[i] = 0; }else if(c == ’\t’) {}}++sel; if(sel >= n) sel = 0; }else if(c == ’\r’) {break; }}6.2 コード: t51.c — 配置のデモ}/* t51.c -- layout interface test */typedef void *layout_t;
layout_t *layout_create();7.2

コード: t52.c — フォームのデモ/* t53.c -- form filling test. */main() {int c, li;char f_name[100] = "", f_age[100] = "", f_occ[100] = "";5

"2. Neutral" };char *f1[] = {"Name:", f_name,"Age:", f_age,"Occupation:", f_occ };main() {int i;
scrinit();i = menuselect("Choose your sex.", m1, 3);scrend();printf("your selection was: %d\n", i);}main() {int i;
scrinit();i = formfill("Fill your info.", f1, 3);scrend();printf("your name:%s, age:%s, occupation:%s\n",f_name, f_age, f_occ);
}

8.3

演習

□ メニューを使ったデータ入力プログラムを作れ。

7.3□ 3 つのバージョンでデータ入力を行って結果を比較せよ。

演習• 入力データは別途用意してあります。

□ 上記のフォームライブラリを使ってデータ入力プログラムを作れ。

「計算機入力の人間学」

9
8

メニュー

□ …ギルブ、ワインバーグ著、木村、米澤訳、共立、1986。

□ メニューも同様にできる (フォームより簡単)• menuselect:

8.1□ …「古い」ところもあるが (e.g.

パンチ室…)、古くないところも。

配列にメニューの項目を用意

10

コード: menu.c

ループを閉じる

menuselect(char *mes, char *menu[], int n) {10.1 とある個人企業…
int sel = 0;
int li = scrlines();□ ループが閉じられている。間違いがあれば修正される。
int i, c;scrclear();
入力
scrputs(1, 1, "^N: down, ^P: up, [RET]: select", 0);（目、耳）scrputs(li, 1, mes);
外界ＤＢ
while(1) {（頭脳）
for(i = 0; i < n; ++i) {出力
int h = (sel == i);（口、手）scrputs(i*2+3, 4, menu[i], h);}scrupdate(); scrpos(li, 1); c = scrgetc();
if(c == ’\r’) {10.2 計算機の導入
break; }else if(c == (’P’ - ’@’)) {□ ループをまわって来るまで間違いは修正できない。
--sel; if(sel < 0) sel = n-1; }else if(c == (’N’ - ’@’)) {++sel; if(sel >= n) sel = 0; }
処理
報告書
出力
}
return sel;
}
外界
ＤＢ

8.2

原文書

コード: t52.c — メニューのデモ/* t52.c --- menuselect test. */char *m1[] = {"0. Male.","1. Female.",

6

データ
入力

10.3

オンライン対話入力

省略時の値の適用

11.4□ 物品ごとの性質→省略時の値を変化□ ループを閉じることができる□ 「原文書」は単なる「出力」になる• 物品ごとに省略時の値を覚えるのは負担• 省略時の値をフィードバック

外界

データ
入力

• 省略時の値を使わなかったときに教えるＤＢ• 省略時の値を使うことも使わないことも許容される
べき
原文書

12

出現順の指定出現順の指定とは

11

省略時の解釈12.1

11.1

省略時の解釈とは?

□ 項目を決まった順序で入れる• cf.

□ 忘れた時は何が起きるか?→省略時の解釈

項目名と項目値のペアで入れる• 「位置パラメタ」「キーワードパラメタ」(IBM 用語?)

• 「やらないことはやりそこないようがない」□ 固定長は数えなければいけないからよくない□ 次のような文を考えて見る。

• 可変長が読みやすく自然、個数も自由• ジョンは車で食料品店に行き、ジョンはパンを買った。
• ジョンは車で店に行き、ジョンはパンを買った。

欄の区切り

12.2

• ジョンは車で店に行き、パンを買った。

□ 出現順→欄を区切る必要がある• ジョンは車で行き、パンを買った。
• ジョンはパンを買った。

• 例:

空白、カンマ、…

• ジョン。

• IBM JCL ではカンマが区切り、空白はコメント開始(!) だった• ( 間)• (まったく何もしない)

12.3
11.2

数量的評価

□ あるデータに対する自然な (頻度の高い値) は?

□ 出現順指定は末尾だけで使われることが多かった• しかし範囲が分かれば真中で使うこともできる( 例:

AAA 3942 6869 Yasushi Kuno 1999.6.1
ABA 045 4011 2845 Yoshiko Kuno 1999.8.25
ACD 869 James Willam Galls 1999.9.1

1、1 ダース、…)• 頻度分布をもとに省略の効果を求めることができる。

□ 「/」などの特別な区切りを使って再同期させる、とい• 頻度分布はあくまで仮定だということを忘れないこ

うのも

と。

• 頻度分布の仮定に対する感度も重要。

11.3

末尾以外での出現順指定• 状態をきちんと考える

構造の利用

12.4

信頼性のための技法□ 出現順指定→冗長度が小さい→短く打てるが、誤りに□ 伝票などの構造→顧客は同一→省略時の値

弱い• 並べ間違いに弱い→自然な順で打たせる、自己識別• 項目数を 4 程度に (例外:

順序が問題でない場合)• 部分並びの利用 (名前、電話番号、…)
7

13

識別情報

14

繰り返し

13.1

識別情報とは?

14.1

繰り返しの意味□ 冗長度をあげてエラーを検出する□ 「何のあたいはいくつ」の「何」• 積極指定:キーワードパラメタ (e.g.

• 自己識別:形を見ただけで分かるもの• しかし「まったく同じものを 2 度打つ」では…
• 必要なところで適宜繰り返しを (部分的に) 使うとよい

NUM=100)

234 234 UI2425

13.2

自己識別情報14.2□ どこにあってもそれと分かる→順序が問題でない、同期
点として利用例外的繰り返し□ 特に注意すべきことだけ繰り返す□ さまざまな自己識別情報• たとえば特に高価、特に大量など• 国名など (USA、JPN、…)□ 計算機の方から確認のため繰り返しを求める• 形で分かる ($20.0、25%、3942-6869、128kg、MR.

• 例外的な場合、繰り返し入力での不一致

JONES□ 分かる解釈から順にふるって、最後まで分からないなら
手作業も可

14.3

繰り返しの有効な利用□ どこから繰り返しを用いるか?

13.3

日付の書式

• 例:
か?

□ すごくいっぱいある

伝票の 2 箇所に同じ数字を書かせる→役に立つ
何の?

• 冗長度はできるだけ情報源に近いところに• 1978.11.1、11/1/78、11.1.78、Nov 1 1978、12.IV.78、12IV78• 月だけ:

14.4

6/1978、6/78• 期間:

1977/1978、1977/78、21-30AUG• 曜日:

TUE4/12

独立性□ 反復によるエラー検出→独立性がなければ意味がない(本当は負の従属性)□ 2000 年問題• 2 人で数えるのなら 1 人目は結果を教えてはいけない
• 例:

13.4

積極指定

ベリをさぼろうとした話□ 一人でも独立性を□ 「NATION=USA」のように種別を明示する• 反復の間に別のことをさせる• 間違いが起きにくい、設計と処理が楽、読みやすい、
順序が自由• 逆打ち、変換 (漢数字とか、切上げ/切捨て、符号化)• 暗黙の繰り返し (別の場所に冗長なものがある)• 自己識別の方が打鍵数は少ないが、思わぬ問題に出
会うことも

14.5

□ うまく組み合わせれば…

三重の繰り返し□ まず間違わないし、多数決で正しい値が分かる→ホント?

• 必要なところだけ積極指定する• 人間が犯しがちな誤りのパターン。「6623546」• 指定しなかった場合は前回の値を引き継ぐ• その他、短縮、抜け、穴埋め、中央への偏り、前の入力への同化□ 結局、三重でも安全とは言えない

8

14.6

圧縮された繰り返し• 名前で探す→近似だから間違うこともある→確認語が有効。

□ 検査桁→一種の繰り返しによる検査• 見出しやポインタで済むというのは迷信。だから確□ 単純な繰り返しとの相違点

認語。

□ 圧縮されていると…

□ 例:• 打鍵数が少ない。手間は大きい。機械が必要。検査が複雑。訂正は難しい。ほぼ数字むき。

241240 GILB
1410KOLBOTN←姓の最初の部分← ZIP コードに地名をつける□ 単純な繰り返しでは…

15.3• 簡単に導入でき検査できる。訂正にも多様な方法が可能。数字に限らず何にでも可能。

確認語の出所□ 原文書の文面や対話から拾い出せる□ 検査桁の計算方法で、検出能力や訂正能力が変化• 弱点のある組み合わせを使わないようにすることも
可能

• 例:

電話番号、品名、値段、• 例:

伝票の走り書き、日付、…

□ 入力データから作り出すこともできる→顧客の名前や電• しかしそのことが忘れ去られると…(理解が困難な方

話番号等

式の運命)
□ 総計による検査も圧縮された繰り返し

15.4

確認語と検査桁• グループが大きくなるほど、誤りの可能性が増し、誤 □ 検査桁→記憶装置を利用*できない*場合の検査法→名前りがあったときそれを見つけるのが大変になるから*導き出せるものでなければならない*。
• コストには誤りを訂正するためのコストも含めなけ□ 確認語→記憶装置を利用*できる*ことを利用した検査法

ればならない→名前から*導き出してはならない*。
□ 例:

15

確認語

15.1

確認語とは?

「82-3942-6869/836」(先頭桁を取り出した確認語) →駄目な設計。検査桁より発見能力が劣る。

• 数字 10 桁のうち 7 桁は検査されない• 3 個の数字も早い段階で入り込んだ間違いには無力□ 外部の情報と比較することで検出/訂正を可能にする余• 数字の読み間違いが検査できない分な情報□ ではどうしたら?

□ 記憶している情報を参照する方法…

「82-3942-6869/kuno」(その電話番号の人の苗字) →この方法でエラーが発見され損なう• ポインタ→計算機内の位置。てっとり速いが融通が
効かない

条件は

• 間違った番号もデータベース中にあり、かつ• キー (見出し) →索引による検索が可能。だが見出し• その人も kuno という苗字のときだけ。

さえあればというのは迷信。

• 名前 (識別子) →情報項目を特定する「傾向のある」 □ 名前と電話番号は独立している (データベースを通じてのみつながっている) →独立性があってこそ、確認語が情報 (第 1 近似)
有効に働く

15.2

確認語の定義15.5□ 「記録内容と比較することで、見つけた記録が確かに求確認語のさまざまめていた通りのものである確率を見積もるのに使われる □ 1 種類の方法でうまく行かない場合も→複数方式 (例:
企業→性名がない)

データ」□ 確認語は一意的に決まるとは限らない→変化を許容

9□ 長さは 2〜4 文字くらいが普通だが上限はない

有効性の評価15.9□ 置き場所は名前に隣接が多いが離れていてもよい (独立□ 数学モデルによる解析性が高まる)□ 同じ確認語や類似した確認語が現われる等→有効性が
低下

15.6

実現

□ 設計の代替案を考える□ よいと思えるものができたら、シミュレーションで検証□ 確認語を選ぶ→それほど重大に考えなくてよい (検索ではなく確認のため)• オフラインのシミュレーション□ 複数キーに同じ確認語がつかないようにする• ライブの (一部オペレータによる実地の) シミュレー□ 確認語の索引をメモリか DB に置いて検索/照合

15.7

ション

誤り訂正への利用□ 確認語は必要なら誤り訂正にも使える□ 確認語で候補を絞ってその中から選択

16

入力検査と適応制御

16.1

範囲検査

□ 入力数値の間違い→範囲検査• 計算機がやる場合→入力と 1 文字抜け、訂正などの比較照合、他の DB データに基づく照合 (例:本の 10□ 範囲はいくつに?

進分類など)

品目ごとに決めるのは難しい• 過去のデータに基づいて決める• 人間がやる場合→ずっと賢くできる• ということは、数値が変動しても適応して行ける□ しかしどちらでも失敗することはある (ゼロにはできな
いと思え)

16.2

□ 逆に予期せぬ利益もある

範囲の調節□ 入力数値による選択肢:

警告なし/警告+範囲調節/確認を求める+範囲調節/確認を求める+範囲調節なし/確• 例: 住所の確認語→引っ越したため不一致エラー→
それは失敗ではなく成功のチャンス (住所未変更を

認+管理者に報告発見できる)□ 限界値が誤って調節されてしまう→毎月自動的に限界値を 10%ずつ減らすことで元に復帰

15.8

不変確認語と可変確認語• ということは、限界値を超えない注文の情報も利用していることになる□ 不変確認語→設計時に割り当て、名前の一部に組み込む「373-467-TBLE」□ 自動調節では、限界値の調節のようすを無作為抽出で検討する必要• 利点: 誤り訂正が確実。偶然検出能力を低下させる
ことを防止できる。
• 欠点:• 不正等で「じわじわと」変更されているのを見つける

独立性が失われている。前段階でのエラーが• その他興味深い状況を発見する

検出されない。

□ さまざまな調節方式:□ 可変確認語→オペレータが規則に従って作る「2345 TG」

平均 (移動平均)、標準偏差、正規分布 (低すぎる値も監視)、ポアソン…

「2345 GIL」

• 運用が用意。訓練が少ない。拡張による問題がおきにくい。独立性が増す (名前そのものが間違っている場合も検出可能)

16.3

パターン検査□ めったに起きない注文→エラーの可能性• 実装は面倒になる。検出/訂正能力がやや低い (複数 □ 固定パターン検査、ビットマップで学習、つけられれば OK)

10

初期設定

16.4

• 利用者が欲しいと思う変動許容ではなく、たまたま
簡単に取り入れられる変動許容だけが実現されてい□ 最初に初期データを入れるのでは大変る→こんなのは許容とは言えない• 自動的に立ち上がるように設計するとよい (適当な値から出発)□ 例:

誕生日を使った身分確認□ 例:

題名の入っていない図書館データベース

17.3

順序の変動

□ 用紙記入症はいけない□ 自然な順序があれば、それに従うのがよい (無理に変動を許容しない)

17

変動の許容

17.1

変動を許容することの重要性□ 処理の都合があれば、計算機の方で並べかえればよい□ メッセージの集団で処理できるとよい (あとで個別修正が簡単であること)□ かっては変動を許容しないことがコストを節約した。
□ 今では変動を許容しないコストは他のいかなるコストよ
り高い。

17.4

内容の変動

□ 標準的な形→時間、金額、数量、範囲など□ 次のような手順で…

□ 同義語のリストを持つ、適応可能なリストも (Zipf の• 要求をはっきりさせる法則)• 現実の運用データを見る□ スペルの変動→スペル検査/訂正• すべての変動を許容しなくてよい。どこまで許容す• 発音の聴き間違いを許容するスペル検査 (BPFVW、RL、るか判断

MN、DT、CKQSZX、GJ をそれぞれグループにしてマッチさせる)• 最初はありふれたものだけ許容すればよい。徐々に(データを取りつつ) 改良

手順の変動

17.2

ニセモノの変動許容

17.5

□ 例:

OS/360 JCL□ 便利なサブルーチンを用意する□ 親切にする//名前 命令 オペランド 注釈• 謙虚な言葉づかい「ジョブ制御文の各フィールドは、名前フィールドが欄 3• メッセージをテストするから始まらなければならないことを除いては、自由形式• メッセージの別形式を用意するで書いてよい。ここで自由形式とは、各フィールドが一定の欄からはじまる必要はない、ということである。各• 手順を間違えてもシステムが壊れない

フィールドは空白で区切る。空白はフィールドとフィー• ありふれたことはたやすくできるようにする

ルドを区切る区切り記号として使われる。」• 監査用の記録をとる□ 実際には:□ 人をロボット扱いすれば、ロボットのようにふるまう。

• フィールド間にはほとんど何個の空白でも入れてよい• フィールドの中には空白を入れてはいけない

17.6• 欄 73〜80 は使ってはならない

性能の見積り□ とんでもなく歪曲された見積りに到達しないこと。歪曲• 欄 72 はある特別の意味にしか使えないの原因としては:• 空白をたくさん置きすぎてフィールドがあまり右の方に来てはならない• 原文書が入力に便利にできていない• 原文書がいろいろあって混ざっている□ 何がいけないか?

• 実は原文書を利用していない11• 実はしろうとが入力している• 1 回かぎりの変換作業□ コストの見積もり• 何がコストになるか (大学は労働がタダ?)• 経費の割り振りの問題□ パイロットテストをする□ 直接入力 (例:テレフォン通販) →順序が自然でないと

…

17.7

変動の積極利用□ 変動を利用して人間を見分けることができる□ 一定時間待って応答がなかったら先へすすむ□ 打鍵タイミングを見張っていると打鍵間違いの発見が可能に□ あまり誤りが多いようなら、その人に何かの問題が…
□ 変動の監視を抑圧に使わない (きっと報復を受ける…)

12