在庫を作っている途中で、簡単な予約も入れました。誰が、いつ、何個使うのか。まだこの頃は、在庫を先に確保しておくくらいの感覚でした。
でも、そこからまた思いました。
私「こういう予約アプリって、世の中にいっぱいあるじゃん。」
A「あるね。」
私「車とか機器とか施設とか。」
A「うん。」
私「だったら、それもこのアプリ一個で予約できたら便利じゃん。」
A「在庫で終わる気、最初からなかっただろ(笑)」
私「いや、これは後から思った。」
最初に考えたのは、本当に普通の予約です。車を使いたい。機器を借りたい。施設を押さえたい。そのたびに「空いてますか?」と確認するのが面倒。
私「カレンダーみたいに空いてる時間が見えて、そこ押したら予約できればいいじゃん。」
A「ここだけ聞けば普通。」
私「だろ?」
A「前回を見たから警戒してる(笑)」
B「技術的にはリソース予約ですね。車両・機器・施設のような共有資源を、時間帯で確保します。」
ところが、在庫予約との大きな違いがありました。
時間です。
例えば、10時から11時まで車の予約が入っている。そこへ、10時30分から11時30分まで別の人が予約しようとする。
私「これは普通にダメでしょ。」
A「時間かぶってるからね。」
B「Interval Overlap。時間区間の重複判定ですね。」
私「当時は本当に『時間かぶってるじゃん』だけ。」
でも、重複しているかどうかだけでも、境目を決める必要があります。
10時から11時まで予約。次の予約は11時から12時。
A「11時ちょうどから使っていい?」
私「前の予約が11時で終わるなら、11時から使えていいでしょ。」
B「そこが境界条件ですね。」
A「『時間が被ってなければいい』の、“被ってない”まで決める必要がある。」
私「作る側だと、こういうのまで決めるんだなって思った。」
さらに、予約したい時間が毎回きれいな1時間単位とは限りません。
私「10時から11時だけじゃなくて、10時30分からとかあるじゃん。」
A「15分単位の会社もあるかもしれない。」
私「30分単位とかね。」
B「**時間粒度(Time Granularity)**ですね。」
A「1時間固定なら楽なのに。」
私「使う側はそうはいかないでしょ。」
A「また現実が実装を殴る(笑)」
時間をどう選ぶかも、気になりました。
例えば、8時〜9時、9時〜10時、10時〜11時、11時〜12時。8時から12時まで予約したい。
私「これ4個全部押すの面倒じゃん。」
A「出た。“面倒”から仕様が増えるやつ(笑)」
私「指でスーッと選べれば楽でしょ。」
A「ドラッグ選択。」
私「そう。」
B「範囲選択ですね。開始位置から終了位置まで、連続した時間枠をまとめて選択します。」
でも私は、スマホでも使いたかった。
A「はい、そこが問題(笑)」
私「まだ何も言ってない。」
A「スマホで指を動かしたら普通はスクロールするでしょ。」
私「する。」
A「でも予約表では、その指で時間も選びたい。」
私「そう。」
A「ほら(笑)」
スマホでは、
指を動かす=画面をスクロールする
でもあり、予約表では、
指を動かす=時間帯を選ぶ
にもしたい。二つがぶつかります。
B「ジェスチャー競合ですね。」
私「俺は『なんで予約選ぼうとしたら画面動くんだよ』くらい。」
A「使ってる側はそうなる(笑)」
ただ、ドラッグだけにもしたくありませんでした。
私「でも飛び飛びで予約入れるなら、ドラッグの方が楽でしょ。」
A「空いてるところ見ながら、そのまま選べるからね。」
私「開始時間と終了時間を直接入れる方法も欲しい。」
A「ドラッグあるのに?」
私「細かい時間なら直接入れた方が早い人もいるでしょ。」
ドラッグで10時〜12時。直接入力で10:00〜12:00。入力方法は違っても、裏では同じ予約として扱う。
B「入力の正規化ですね。」
A「Bが言うと急に難しそうになる(笑)」
A「一回ここまで整理しよう。」
私「車・機器・施設を時間で押さえる。」
B「リソース予約。」
私「予約時間を被らせない。」
B「時間区間の重複判定。」
私「終了と次の開始の境目を決める。」
B「境界条件。」
私「15分、30分、1時間みたいに予約単位を決める。」
B「時間粒度。」
私「指でまとめて選ぶ。」
B「範囲選択。」
私「スマホのスクロールと予約選択がぶつかる。」
B「ジェスチャー競合。」
私「ドラッグでも直接入力でも同じ予約にする。」
B「入力の正規化。」
A「……『空いてる時間押したい』だけで、もうこれ?」
私「まだ予約できるようにしただけだよ。」
A「その“だけ”を信用しないことにした(笑)」
そして、実際の業務に寄せていくと、もう一つ必要になりました。
私「これ、どこの現場で使うのかも欲しいじゃん。」
A「使用先?」
私「そう。」
A「予約した人が分かればよくない?」
私「予約した人と、実際に使う現場は別でしょ。」
例えば、事務所にいる人が現場で使う車を予約する。予約した人と、実際に使う場所は別です。
私「だから使用先も持たせた。」
B「予約者・予約対象・利用先を結び付けるわけですね。」
A「また予約データに一個増えた(笑)」
私「必要でしょ?」
A「必要だから困るんだよ(笑)」
そして、車両、機器、施設。これを全部別々に作るのも、面倒だと思いました。
私「基本は同じじゃん。」
A「何が?」
私「何を、いつ、誰が使うか。」
A「細かいルールは違うよ?」
私「でも共通にできるところまで別々に作る必要ないでしょ。」
B「共通化・抽象化ですね。」
A「また始まった。」
私「一回共通に作れば――」
A「次から楽じゃん、だろ?」
私「先に言われた(笑)」
もちろん、車両・機器・施設で細かい違いはあります。予約できる時間。時間単位。表示方法。カテゴリ。
私「そこは後で変えられるようにすればいい。」
A「……その話、絶対また大きくなるよね?」
私「なった(笑)」
予約者名についても、常に表示するのではなく、必要に応じて表示を切り替えられるようにしました。
B「予約データそのものと、表示制御を分けたわけですね。」
そして、予約にはもう一つ、かなり面倒な問題が残ります。
A「同じ車の同じ時間を、二人が見てる。」
私「うん。」
A「二人の画面では、どっちも『空いてる』。」
私「うん。」
A「ほぼ同時に予約ボタン押したら?」
私「……それもある。」
B「表示した時には空いていても、予約を確定する瞬間にも空いているとは限りません。」
A「どうするの?」
私「その話は、あとでちゃんとやる。」
A「逃げた(笑)」
私「違う。それだけで一話の量(笑)」
これは後の開発で、本当に大きな問題として戻ってきます。
そして、予約を作っていくほど、画面も機能も増えていきました。
私「今度はさ。」
A「まだあるの?」
私「使いたい機能を毎回探すの、面倒じゃん。」
A「……次はそこ?」
私「よく使うやつ、すぐ開けた方が便利でしょ。」
A「また“面倒”から始まった(笑)」
次回
在庫に続いて、車も、機器も、施設も予約できるようになりました。
便利になった。
でも、便利にしようとして機能を増やした結果、今度は別のことが気になりました。
「使いたい機能を毎回探すの、面倒じゃん。」
よく使うものくらい、すぐ開ければいい。
今度こそ、画面を少し使いやすくするだけだと思っていました。
――お気に入りから、共通UIそのものを考え始めるまでは。
連載公開分(クリックで開く)
- # 【プロローグ】素人エンジニアが自分でアプリ開発できると甘く見てた 全16弾無邪気な実装 vs 架空エンジニア2人の容赦なきツッコミ ※便利かなと思ってどんどん追加しちゃうんだよね
- #1「在庫が見たいだけ」だったのに、引き算ひとつから在庫引当と多目的最適化まで始まった ※総在庫・予約在庫・有効在庫を分けた瞬間、ただの在庫表示が別物になった
- #2「予約機能もこのアプリ1個にまとめれば便利じゃん」で、“時間”が一気に牙をむいた ※時間重複・境界条件・時間粒度・スマホ操作まで、空いてる時間を選ぶだけでは終わらなかった
- #3 「機能増えたら毎回探すの面倒じゃん」で、お気に入りから共通UI設計まで広がった ※機能を増やした結果、「何を作るか」より「どう辿り着くか」が問題になった
- #4「普通の組織図でいいじゃん」で一人を複数部署に入れたら、“多対多”が始まった ※兼務・複数所属・部署別役職・過去履歴が一気に絡み始めた
- #5「どこの現場で使うかも持てばいいじゃん」で、物件マスタが在庫・予約・人を全部つないだ ※機能ごとにバラバラだった情報が、共通マスタを境に一つのシステムへ変わり始めた
- #6「会社ごとにちょっと変えたい」で、設定駆動とバリデーションが殴り合いを始めた ※柔軟にしたら、「自由に設定させすぎない仕組み」の方が難しくなった
- #7「ログインできたからって何でも触れたらまずいじゃん」で、認証より面倒な認可の沼に入った ※管理者か一般かでは足りず、「誰が・誰に・何をできるか」まで判定することになった
- #8「二人とも空いてる画面を見てたら、どっちが勝つの?」でRace Conditionが牙をむいた ※在庫も予約も、画面に表示された「空き」を信用しただけでは守れなかった
- #9「自分の在庫も持てた方が楽じゃん」で、“場所・所有・利用範囲”が全部別問題だった ※マイ在庫・現場在庫・共有在庫を分けたら、在庫数よりスコープ管理が難しくなった(近日公開予定)
- #10「申請もこの中でできた方が楽じゃん」で、CRUDの裏に状態遷移が増殖した ※申請・承認・差し戻しを入れた瞬間、「保存できる」だけでは何も足りなくなった(近日公開予定)
- #11「資格もQRで見られたら早いじゃん」で、“全部見せる”より“必要な答えだけ返す”方が難しかった ※資格・個人QR・権限をつないだら、識別より情報開示の方が本題になった(近日公開予定)
- #12「一輪車を“ネコ”で探せないの不便じゃん」で、Canonical IDと人間の曖昧さを両立させることになった ※人間には優しく、内部は厳密に−−別名検索から正式IDへ収束させるまで(近日公開予定)
- #13「機能増えすぎて説明する方が面倒」で、“どれが今の正解?”問題がコードの外まで広がった ※ヘルプ・仕様・会話・引き継ぎがズレ始め、Single Source of Truthが必要になった(近日公開予定)
- #14「Codexなら全部見てくれるじゃん」で、AIの作業速度が人間のレビュー限界を超えた ※コードベース横断調査が便利すぎて、変更範囲・Git・差分・安全コミットが主役になった(近日公開予定)
- #15「テストこんなに通るじゃん」で安心しかけたら、“全部緑なのに間違ってる”が普通に出てきた ※横断テストで見えた、Interaction Bug・境界値・期待結果そのものの罠(近日公開予定)
- #16「人間+AI+Codex、ここまで来たら完成でしょ?」で、開発体制そのものをプロにダメ出しされた ※完全な、ど素人から辿り着いた現在地−−でも最後まで人間が働きすぎだった(近日公開予定)
- ♯エピローグ「作れた」で終わりじゃなかった。むしろ、そこからが本番だった ※やっぱりプロのエンジニアは凄いですね。(近日公開予定)


