書いたコードがエラーで動かない。そんな時の修復手順について
書いたコードがエラーで動かない。そんな時の修復手順について
現在、プログラミングスクールのお手伝いをさせて頂いているのですが「お手本の通りに書くと出来るけどそれを変更したときのエラーについていけない」というお話がありました。
丁度過去に納品したシステムの不具合が上がってきていたため、これを例にしてエラーを修正するプロセスを解説しようと思い記事にまとめてみました。お悩みのある方、ぜひご一読ください。
納品したシステムで発生したエラー
以前、依頼を受けて作成/納品させて頂いた楽天などのモールの店舗分析結果を取得するAPPで2021/08/21以降データが取得できなくなったとの連絡があり週末対応していました。どんな内容か確認すると「アプリを起動しても何も動かない」との事。
納品させて頂いて半月以上経過しましたが、その間コード自体は変わっていないはず。(私いじってないので)
そうなると、「インストールしているPCの変化」「読み込みに行くサーバー(楽天市場RMS)の変化」が原因究明の捜査対象となります。
ということで、問題の発見とその過程のプロセスをプログラミングを勉強している人向けにまとめてみたいと思います。
教科書的な記載をするとバグ修正プロセスは以下の通り
教科書的とあえて書く理由は「それで解決できるモノならいいけどね」という意味を込めています。
- 発生しているエラーのメッセージを書き出す(テキストエディタなどにコピペしておく)
- そのメッセージをGoogleさんに貼り付けて検索
- 1ページ目に表示されているリンクを全て開く
- 開いたリンクをパッとみて、共通項を見つける
- 先ほど開いたリンクは閉じずに、見つけた共通項で検索してみる
- 発生しているエラーと照らし合わせて、実行してみる対策をピックアップ
- 修正するコードのバックアップとった上で、エラー対策を実際に組み込んでみる
- エラーメッセージの違いを確認、変わりなければ対策として間違い。メッセージが変わった場合は前進か後退のどちらか。
- 1から8を繰り返して解決に近づけていく
多くのプログラマが経験したエラーの場合はこの流れでも対策できると思います。
組んでいる時はこの操作が多分多いので、教科書としてはこのルートなんでしょうね。
でもこれで行っていると多分詰まります。絶対詰まります。自分の思考が止まります。
システム屋が行っている愚直だけど効果のあるバグ修正プロセス
これは私が師匠に教えて頂いた方法です。
- 問題の発生しているファイル(コード)に当たりをつける
- そのファイル(コード)にて、1工程ごとにlogを吐き出すようにコードを改修する(ログを掃き出しまくる)
- Logが消えた場所から問題となっているコードを特定する
- そのコードが問題となった原因を調べる(Google先生に聞いたりコードを分割して実行してエラーの違いを調べたり)
- 調べた内容を実装てみる
- エラーメッセージの違いを確認、変わりなければ対策として間違い。メッセージが変わった場合は前進か後退のどちらか。
- 4〜6(悩んだ時は3〜6)を繰り返し解決に近づける。
「動いていたシステムが動かなくなった時」の問題発見にはこのような手順を踏むのが一番効果あります。
最初の当たりすら立たない場合はとにかく至る所にログを吐き出すコードを仕込み、徐々に問題箇所包囲網を狭めていきます。
問題となっているコードの特定。そして、そのコードが問題となっている原因の究明。
これができれば問題の原因は綺麗に取り除く事ができます。という事で、上記項目は目指すべき着地点となります。
今回のバグを資料に具体的なエラー修正プロセスを追尾
最初の問題「アプリが起動しない」
発生していたエラーは最初の項に記載した通り「アプリが起動しない」です。
起動に関しては標準でログ吐き出し機能をつけているので原因が特定できます。
エラーログを確認すると、読み込むCSVの2行目に入っているハズの【接続モールの指示】にルールに従った値が入っていないとの事。
確認すると、2行目に来るべき値が1行目に記載さてていました。
「うん、これじゃデータ不備と判断して起動しない(というか起動後に予定した動作は行わず終了する)」
ということで、この点指摘させて頂いて、本来のCSVデータに変更。
「それでもやはり取得ができない」と指摘をいただきます。多分取得できないから色々いじってみて、CSV変にしたんでしょうね。
2段目の問題発生「【アクセス集中】と出てきてデータの取得ができない」
最初の問題は解決しましたが、次の問題が発生します。
「RMSからデータを取得するアプリにて、アクセス集中の案内でデータ取得ができない」
発生していたのはこんなエラーです。
アクセス集中?
まぁ確かにスーパーセール直前の作業数の多いタイミングではあるけど、店舗のログインに耐えられないほど脆弱なサーバーを利用しているとは考えにくいです。となると、どこかに問題があるはず。
で、問題のエラーが発生する時に取得しようとしてたデータと、その取得スクリプトに当たりをつけます。
システムを組んでいるのはWindowsのVBScriptなので、WEBアプリでは発生しない不確定な要素が3つあります。
- Windowsの更新によりコードの改修が必要になった可能性
- ブラウザ機能の変更により使用していたDOM操作に問題が発生した
- 別のアプリを入れるなど、PC内の変更でシステムが動かなくなった
つまり、問題の原因には「アプリそのもの」と「アプリ周辺環境」の2つの因子が存在するということです。
当たりを付けたコードのどこでエラーが出ているかLogを書き出しまくって特定する
VBScriptなので、実際にはLog記載ではなく MsgBox 使いましたが、目的は同じです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
Option Explicit Dim objIE Dim url Dim ShopCode '.... Include("common.vbs") MsgBox("1") Include("Rakuten/R_common.vbs") MsgBox("2") On Error Resume Next MsgBox("3") strFormattedDate = DateAdd("d",-2,now()) MsgBox("4") ShopCode = Wscript.Arguments(0) MsgBox("5") fileDirectory = Wscript.Arguments(1) MsgBox("6") If IsDate(Wscript.Arguments(2)) = False Then MsgBox("7") AddGetDate = Null MsgBox("8") Err.Clear MsgBox("9") Else MsgBox("10") AddGetDate = Wscript.Arguments(2) MsgBox("11") End If MsgBox("12") If IsNull(fileDirectory) Then MsgBox("13") Elseif fileDirectory = "" Then MsgBox("14") Else MsgBox("15") End If MsgBox("16") Set objIE = CreateObject("Shell.Application").Windows(CreateObject("Shell.Application").Windows.Count - 1) MsgBox("17") url = "https://rdatatool.rms.rakuten.co.jp/access/?menu=pc&evt=RT_P06_01&stat=1&owin=" MsgBox("18") objIE.Visible = True MsgBox("19") objIE.Navigate2 (url) MsgBox("20") Do While objIE.Busy = True Or objIE.readyState <> 4 MsgBox("21") WScript.Sleep 100 MsgBox("22") Loop MsgBox("23") WScript.Sleep 5000 MsgBox("24") Set url = Nothing MsgBox("25") '.... MsgBox("40") |
実際のコードを載せるわけにはいかないので、適当なサンプルですが、こんな感じでとにかくログを出させまくります。
MsgBox(“1”)〜MsgBox(“3”)なんかは私的には不要なのですが、今回はお勉強目的の記事なので「とにかくわからない場合は書く」の例として記載してあります。
実行すると、MsgBoxに20のカウントが実行されませんでした。
ログが出なかった直前のコード(コード群)に問題がある
今回の場合だと、20がコールされなかったので、20の前に記載しているコードを疑います。
1 |
objIE.Navigate2 (url) |
これですね。これは【IEでURLを開け】という命令になります。
つまり、エラーの発生場所を追うと【IEで指定したURLを開いた結果、上記503エラーが発生した】が事実として確定となります。
原因箇所がわかったら、色眼鏡をつけづに理由を探る
最近のWindowsは【IEの完全撤廃】を考えているようです。
私はこの色眼鏡で見てしまい今回の解決に余計な時間をかけてしまいました。
今回でいえば、IEだからエラーを出しているのか、IE以外でもエラーが出るのか、ここら辺の確認は最初にすべきでした。
原因の思い込みは間違えた方向に意識をリードされてしまうので要注意です。
【IEで指定したURLを開いた結果、上記503エラーが発生した】この事実から推測できる問題の理由は下の通りです。
- 本当にアクセス集中が発生している
- アクセスできないページにアクセスしている
- サーバー側がIEでの接続を感知してブロックしている
- IEで(DOM操作の方法など)仕様変更がありコードの書き方が変わった
- VBScriptの更新が入り利用しているコードが廃止になった
私はIEを排除したいMicrosoftに楽天市場が対応した可能性を疑いました。
(実際、今RMSにログインすると「IEは推奨してないよ」というメッセージ出てきますし)
ただ、これが原因だとすると改修に掛かる工数が跳ね上がります。ということで、頭に入れておきながら、次の原因を探っていきます。
Windowsの更新パッチで動作おかしくなった?
windowsの月例パッチは20日ごろから始まることが多いです。
そのためタイミング的に「あり得そう」と考えました。
これだったら過去に戻して見れば解決です。
で実行してみましたが、解決しませんでした。
実際の答えは楽天市場内でURLの変更(サブドメインの変更)があった
実際の答えは先程の [項目2:アクセスできないページにアクセスしている] でした。
ここでも私の思い込みがあって、アクセスエラーは通常403を出すので、503と言う所に引っかかってしまいミスリードしました。
システムのRouterではページは存在しているが、アクセス不能に設定している
この場合はForbiddenにはならないので、システムがエラーを吐く500番台が適用されます。
う〜ん、完全にノーマークでした。
ということで、21日にRMSのサブドメイン変更(終了)があったようです。
具体的には下のような変更でした。
=> https://datatool.rms.rakuten.co.jp/rt/?menu=pc&evt=RT_P06_01&stat=1&owin=
まとめ
今回は具体的な修復プロセスを記載してみました。
記事を追いながら【現象の確認 => エラーの場所特定 => 推測とテスト => 修復】というプロセスが見えたのではと思います。
エラー修復(意図したのと違うも含め)1丁目1番地はエラーの場所特定のための「ログの書き出し」です。
これはコードの勉強中でも同じことです。
まずは「問題はどこか」を知ること。
これを疎かにしていると、実際の現場に入った時も苦労すると思います。
現場作業、コーディングのお勉強、この記事を閲覧してくださっている方のポジションは様々だと思います。
さぁ、本日も頑張っていきましょう!
-
前の記事
LaravelのModelの【guarded】について勘違いしていた件 2021.08.25
-
次の記事
システム案件で月収が100万を超えることになりました。 2021.09.02
コメントを残す