業務システムの「取引先を選ぶと品目の候補が絞り込まれる」機能で、JavaScriptの”名前の付け方”と”起動する順番”に二重にハマった話(実体験)

はじめに

これまで2回、「[Access業務システムを、Claude Codeで丸ごとRailsに移植してみた話(実体験)](https://jijigrammer.info/programming/3740/)」「[Railsで作った業務システムの「数字入力欄」が、日本語入力(IME)を使うユーザーには打てなかった話(実体験)](https://jijigrammer.info/programming/3747/)」という2本の記事で、あるお取引先の在庫管理業務システムをAccess/VBAからRailsへ全面移植したときの「ハマった話」をお伝えしてきました。

今回は第3弾です。前回・前々回同様、お取引先を特定できないよう細部は一般化してお伝えします。

今回は「たまにしか起きない」系のハマりどころ

前々回は「動かない・エラーが出る」タイプ、前回は「エラーは出ないが実際に使うと困る」タイプの不具合でした。今回はそのどちらとも少し違う、**「特定の順番・特定の条件が揃ったときだけ、たまに動きがおかしくなる」**という、一番厄介なタイプの話です。

舞台になったのは、入庫依頼を新規登録する画面に追加した、「取引先を選ぶと、それに合わせて他の欄が自動で反応する」という機能です。具体的には、取引先を選ぶと①その取引先がいつも荷物を置く保管場所が自動で入力され、②品目を選ぶ欄の候補が、その取引先向けの品目だけに絞り込まれる、という作りにしました。都道府県を選ぶと市区町村の候補が絞り込まれる、あの手の仕組みのイメージです。

一見よくある機能ですが、実装してみるとJavaScript側で2つの落とし穴にはまりました。

## 実際にハマったところ

① 変数の名前が、たまたま「Value」で終わっていただけで壊れた

この画面のJavaScriptは、Stimulusという、Railsとの相性がよいフロントエンド用の仕組みで書いています。Stimulusには「部品(コントローラ)に値を持たせて、値が変わったら自動で処理を呼び出す」という便利な機能があるのですが、値の名前を宣言すると、実際に画面のHTML属性に落とし込まれるときに、末尾へ自動的に「Value」という言葉が足される、というルールがあります。

最初、品目候補を絞り込む条件のことを「constrainValue(絞り込みの値)」という、素直で分かりやすい名前にして書いていました。ところが、これだと「Value」という言葉の後ろに、さらに仕組み側が「Value」を足してしまい、想定していた属性名と実際にブラウザ上で監視されている属性名がずれてしまいます。結果として、値を変更しても変更を検知する処理が一切呼ばれない、という状態になりました。

厄介なのは、この状態でもエラーは一切出ないということです。画面は普通に表示されるし、他の操作は問題なく動く。ただ「取引先を選んでも品目の候補が絞り込まれない」という、機能そのものが静かに死んでいるだけなので、パッと見ではどこがおかしいのか見当がつきません。

原因が分かってからの対応は単純で、名前を「constrainValue」から「constrainTo(絞り込み先)」という、そもそも「Value」で終わらない名前に変更しただけです。ただ、二度と同じ事故を起こさないよう、なぜこの名前にしたのかという理由そのものをコードのコメントとして残してもらいました。名前の付け方ひとつで機能が丸ごと沈黙する、という経験は初めてで、正直かなり印象に残りました。

② 画面の部品同士の「起動する順番」が、状況によって前後する

もうひとつ厄介だったのが、順番の問題です。この画面には「取引先を選ぶ部品」と「品目を選ぶ部品」という、別々のJavaScriptの部品が同時に動いています。取引先を選ぶ部品が、品目を選ぶ部品に対して「この取引先に絞り込んでね」という指示を出す作りなのですが、この2つの部品、画面が表示されたときにどちらが先に準備を終えるかが、状況によって入れ替わることがある、ということが分かりました。

もし品目を選ぶ部品の「初期の準備」が、取引先を選ぶ部品からの指示を受け取ったあとに終わるような書き方をしていると、先に届いた指示の内容を無視して、まっさらな状態で準備が完了してしまいます。結果、たまたま起きる順番によっては絞り込みが正しく効いたり効かなかったりする、という再現性の低い不具合になっていました。

対応としては、「指示を受け取っても大丈夫な準備」と「他の部品からの指示より後に終わることが保証されている準備」を、Stimulusの仕組みの中で明確に分けて書く形にしました。要は「誰が何を、いつまでに終わらせておく必要があるか」という順番の保証を、思い込みではなくきちんと仕組みのルールに沿って書く、という当たり前のことを徹底した形です。地味ですが、こういう「たまに起きる」系の不具合は、原因が分かってしまえば対応自体はシンプルなことが多いです。

③ (おまけ)検索して絞り込んだ状態で登録に失敗すると、検索条件も消える

これは前の2つとは別の画面で見つかった、小さいけれど地味にストレスの溜まる話です。品目や取引先の条件で検索して一覧を絞り込んだあと、「この場ですぐに新しいデータを登録したい」というときのために、一覧画面の中に簡易登録欄を用意していました。ところが、ここで入力ミスがあって登録に失敗すると、エラーメッセージと一緒に画面がもとの一覧に戻るのですが、そのとき使っていた検索条件まで一緒にリセットされてしまい、また最初から検索し直しになる、という挙動になっていました。

エラー自体はきちんと表示されるので気づかれにくいのですが、実際に使う立場からすると「せっかく絞り込んだのに、入力ミス1つでまた振り出しか」となる、じわじわ効いてくる不便さです。対応は、登録に失敗して同じ画面に戻すときに、直前まで使っていた検索条件を一緒に持ち回すようにしただけですが、地味に体感が良くなった修正でした。

非エンジニアの実感として

今回の3つに共通しているのは、どれも「テストでは気づきにくい」種類の不具合だったということです。①は名前の付け方という、動作確認しただけでは見た目に一切現れない話ですし、②はそもそも毎回同じ順番で起きるとは限らない話、③はエラー自体は正しく出るので「バグ」とすら認識されにくい話でした。

こうした話でClaude Codeが助けてくれたのは、原因を突き止める調査力もさることながら、「なぜこう直したのか」という理由をコードのコメントとしてそのまま残してくれたことでした。①の名前の話では、なぜこの名前を選んだのかという理由自体を、②の順番の話では、どの処理がどの順番で終わることを前提にしているのかという設計判断を、それぞれコード上に書き残してもらいました。自分で読み返しても、半年後の自分や別の担当者が同じ事故を繰り返さずに済みそうだと感じています。

まとめ

業務システムの「取引先を選ぶと関連する欄が自動で反応する」機能を作る中でハマった話を3つお伝えしました。

– フレームワーク側が変数名に自動で接尾辞を足す仕組みがある場合、その接尾辞とかぶる名前は避ける。エラーが出ないまま機能だけ静かに死ぬことがある

– 画面上で複数のJavaScriptの部品が同時に動くときは、「どちらが先に準備を終えるか」を思い込みで書かず、仕組みが保証している順番に沿って書く

– 検索や絞り込みの条件は、エラーで画面に戻すときも一緒に持ち回す。エラー自体が正しく出ていても、使い勝手としては地味に不便になる

前回の「[Railsで作った業務システムの「数字入力欄」が、日本語入力(IME)を使うユーザーには打てなかった話](https://jijigrammer.info/programming/3747/)」、前々回の「[Access業務システムを、Claude Codeで丸ごとRailsに移植してみた話](https://jijigrammer.info/programming/3740/)」もあわせて読んでいただけると、プロジェクト全体の流れが分かりやすいかと思います。

同じような「名前」や「順番」のせいで動きがおかしくなった経験がある方、ぜひコメントで教えてください。

コメント