見出し画像

プログラマ探偵の事件簿:Submitボタンが起こす超常現象

超常現象かと思われるような不可解なソフトウェアの動作も原因がわかってみれば単純なことであったという話である。

事件の始まり

浦和レッズレディースが劇的に勝利した試合をTV観戦しながらログ分析ツールTWLogAIANの改善を行っていた時のことである。
改善した機能の最終テストのため一通り操作してみると不思議な動きをした。抽出パターンのテスト画面で抽出パターンを前の状態に戻すボタン

抽出パターンを戻すボタン

を何回かクリックすると何故か、ようこそ画面

ようこそ画面

に戻ってしまった。何度やっても再現する。

処理は単純なのに何故だ!

問題の処理のソースコードを確認してみる。
ボタンの表示はSvelteで書かれている。

 <h5>抽出パターン
  <button class="btn btn-sm ml-1" on:click="{resetGrok}"><Reply16/></button>
 </h5>

ボタンをクリックした時の処理は、

  const oldGrok = [];
  const resetGrok = () => {
    if (oldGrok.length > 0) {
      grok = oldGrok.pop();
    } else {
      grok = "";
    }
  };

だけの単純なものだ。
果たして何処に問題があるのだろうか?

デバッカーは何も教えてくれない

ソフトウェアの問題を調べるための定石であるデバック画面を表示して再現してみた。しかし、何も問題を教えてくれない。次の定石console.log()で処理の流れを追ってみた。何とそれすらもデバッガーには表示されない。
デバッカーは沈黙を守っている。天にいる助手の猫も何もヒントをくれない。

あらゆる可能性を試行錯誤

ボタンを押した時の処理は単純である。関係ありそうな部分を削除したり変更して試してみれば現象が起こらなくなるはずである。

  • 関数の中で何もしない

  • 変数名を変える

  • ボタンをクリックしても処理を呼び出さない

  • ボタンにつけているクラスを削除する

  • ボタンの表示位置をかえる

  • ボタンで表示するアイコンを変える

  • etc

思いつくことは全てやってみた。修正してビルドして試すには数分かかるため気がつけば4時間近く試行錯誤していた。繰り返し操作のしすぎで腕が痛くなってきた。

問題のソースコードだけでは見えぬものがある

天にいる助手の猫がいたずらをして超常現象を起こしているのではと疑い始めた頃である。「問題のソースだけ見ていても見えないものがある」と助手の猫が濡れ衣をはらすためにヒントをくれた。
そこで、同じ画面にある他のボタンのソースと比べてみた。他のボタンでは問題の現象が起こらないためである。

  <button class="btn btn-secondary mr-1" type="button" on:click={back}>
    <X16 />
    終了
  </button>

違いが見えた! 問題のボタンにはtype="button"がない。

苦労の後に残る教訓

問題のボタンにも

        <h5>抽出パターン
          <button type="button" class="btn btn-sm ml-1" on:click="{resetGrok}"><Reply16/></button>
        </h5>

のようにtype="button"を付けて解決した。

のボタン要素の説明を良く読むと、

ボタンがサーバーにデータを送信するためのものでない場合は、 type 属性を button に設定することを忘れないでください。さもないと、フォームデータを送信して (存在しない) レスポンスを読み込み、文書の現在の状態を破棄してしまうおそれがあります。

MDN

と書いてあった。
Wails+Svelteの環境(Svleteだけの環境)では、最初の画面に戻ってしまうという超常現象が発生する。他の開発でも同じような経験をしたが何気なく解決できたため記憶に残っていなかった。今回は、4時間も悪戦苦闘して腕も痛くなったので、しっかりと教訓となった。
天から助手の猫が「わしを疑う前に、自分を疑え!」と言っているようだ。


開発のための諸経費(機材、Appleの開発者、サーバー運用)に利用します。 ソフトウェアのマニュアルをnoteの記事で提供しています。 サポートによりnoteの運営にも貢献できるのでよろしくお願います。