デプロイしたら挙動が違う!?どうしよう?

 今日も見に来て下さってありがとうございます。石川さんです。ここのところTMのツール開発しているのですが、ローカルで作成したときに確認した挙動と、サーバーにデプロイしたプログラムの挙動が違っています。どうしてなのか、調べてみました。
結論を言うと、原因は突き止めて解決しましたが、理由までは分かりませんでしたよ。。。

違いは…

まずは、ローカル側の挙動です。箱のデータはデータベースに書けるようになったので、線を引こうとまずは箱を探して、一つ目の箱から二つ目の箱へ1:Nのゼロありの線を引くようにしました。まだ作りかけなので、線は青いです。

ローカル側 想定通り動いています

次に、サーバー側の挙動です。一つ目の箱は右のサイドから、二つ目の箱の左のサイドへ線を引く、という設定になっているはずなのですが、なぜか両方共の箱の上のサイドになってしまいます。プログラムはまったく同じ状態のはずなので、謎です。

サーバー側 想定と少し異なります

そして、この接続点は移動できるように作っているので、サーバー側のプログラムで同じ位置になるように移動してみたところ、変な位置になってしまいました。なんてこったい。

サーバ側 接続を移動して見たところ やはり想定と異なります

いやいや、これ解決できるのかなぁ。。。

使える武器は…

Web開発の実務経験もセミナーなどで教わったこともなくて、すべて独学なので、こういうときに使える武器が全くないのですよね。ブラウザ(Chrome)にデバッガはついているのですけど、サーバー側にデプロイした状態だと、Typescriptのソースコードはjavascriptに変換されてしまっていて確認できなくなっているのですよね。と、いうことで、console.log()しか思いつきません。ま、あるものでやるしかないですよね。と、いうことで、まずは、Sideの情報と、1:NのときのNの情報がうまく処理できていないようですので、どうなっているのかログを出力してデプロイすることにします。

と、ソースコードを見始めましたが、使っているHTML5 Canvas JavaScript フレームワーク(KONVA)の使用方法が原因のようです。表示する図形、この場合は、接続点ですが、それぞれSideと1:Nの設定値のバリデータを手作りしていましたので、ログ出力する前に、ここのバリデータを使用しないように変更して、ビルド、デプロイしてみました。

すると、、、なんと、正しく動作しました!
ズバッと解決、、、は、しましたが、、、気持ち悪いですねぇ。

ソースコードの違い

原因となった個所の、修正前のプログラムと修正後のプログラムを参考までに載せておきます。接続点の最大値を、Infinityにしたのですが、KONVAではInfinityは数値ではないようでバリデータがなかったため、KONVAのValidatorを参考にして、以下のように手作りしてみました。

-- 修正前(ローカルは動くが、サーバ側は正しく動かない)
Factory.addGetterSetter(TMConnectionPoint, 'maximum', "",
  function(val:any,attr:any){
      if (Konva.isUnminified) {
          if (!(Util._isNumber(val) || val === Infinity)) {
              Util.warn('[' + val.toString() + ']' +
                  ' is a not valid value for "' +
                  attr +
                  '" attribute. The value should be a number or an Infinity.');
          }
          return val;
      };
  });

ビルドしてデプロイしたらローカルと挙動が変わってしまったので、KONVAのソースコードと同様となるように作り直しました。get~Validatorというファンクションをつくって、それをセットする、というやり方でしたのでそちらに習ってみました。違いとしては、Konva.isUnminifiedのフラグをチェックするタイミングです。タイミングの違いによって、挙動が変わったのかもしれません。JavaScript初心者なので、これ以上追っていくと時間がいくらあっても足りないので諦めます。(あ、AngularはTypeScriptでしたね。どっちにしても初心者でした。。。)上記のスクリプトではundefinedを戻していないよ、という、エラーは出ていなかったのですが、ファンクションを切り出したところでエラーが出てきたので追記しました。もしかしたらこの程度の些細な差、なのかも知れません。

-- 修正後(ローカルもサーバ側も正しく動作する)
function getNumberOrInfinityValidator(){
  if (Konva.isUnminified) {
    return function(val:any,attr:any){
          if (!(Util._isNumber(val) || val === Infinity)) {
              Util.warn('[' + val.toString() + ']' +
                  ' is a not valid value for "' +
                  attr +
                  '" attribute. The value should be a number or an Infinity.');
          }
          return val;
      };
  }
  return undefined
}
Factory.addGetterSetter(TMConnectionPoint, 'maximum',"", getNumberOrInfinityValidator());

まとめ

Web開発では、ローカルでうまくいったからと言って、サーバにデプロイしてもうまく動くとは限らない、ということを知りました。そして、そのような事態になったときは、とても心細いですね。