活動記録の最近のブログ記事

その悲劇は、PHPの巨大なクラスをリファクタリングしたのが原因で起こりました。


「フォームの送信ボタンを連打すると発生するとDB上で2重登録されてしまうバグがあり、その問題に対処するために確認画面に遷移したときに重複レコードを削除することになっているはずが削除されない」というものでした。


リファクタリング前のクラス


class myClass {
...
function doSomething($user_id)
{
$sql1 = "SELECT * FROM tb1 WHERE user_id = " . $user_id;
....
$sql2 = "DELETE FROM tbl1 WHERE user_id = " . $user_id;
}
...
}


リファクタリング後のクラス(バグ有り)

class myClass { 
 ...

function doSomething()
{
$sql1 = "SELECT * FROM tb1 WHERE user_id = " . $this->gerUserId();
....
$sql2 = "DELETE FROM tbl1 WHERE user_id = " . $user_id;
}
...
}


いわゆる「問い合わせによる一時変数の置き換え」をやろうとして、置換が漏れてました。

($user_id を $this->getUserId()に置き換えたかった)

しかもこのバグを本番にアップして2ヶ月間も気づかず放置。

上記のDELETE文はSQL文法エラーで実行されず、消さなきゃいけないデータが2ヶ月も消えないまま残ってしまっていた。。。


敗因


最初に頭によぎったことは、「Perlで書いてれば!!Perlなら絶対use strictって書くからこんなミスしないのに!!」
こともあろうに私は言語のせいにしようとしました。

もちろんPHPに非があろうはずがありません。
悪いのは私であって、言語ではありません。


E_STRICTを有効にしてなかった

Perlのuse strict;を羨むくらいなら、E_STRICTを有効にしておけばよかった。


自動単体テストを書いていなかった

リファクタリングには自動単体テストが必須なわけですが、私はこれを怠けたのです。

「それってリファクタリングちゃうやん」と言われたら、まったくその通りです。


手動テストをしていなかった

上記delete文がちゃんと機能しているかを確認する手動テストすらしていませんでした。
典型的なEdit & Pray(編集して祈る)開発スタイル !!


本番サーバでのエラーログを見てなかった

上記スクリプトはSQL的に文法エラーなわけで、当然サーバのエラーログにもエラーが残っていました。
しかしその文法エラーのエラー文を見ても、上記スクリプトが原因だと気づきませんでした。。。


ユーザからの声に気づけず

「動作がおかしい」という話をここ数週間聞いてたのですが、どうしてもバグが再現しないので「バグじゃないかもしれない」などと甘いことを考えていました。

本気でバグを探そうという気概が足りなかったのかもしれません。


心がまえ

「自分はリファクタリングに慣れてるからテストなんか書かなくても大丈夫」という慢心がありました。

この慢心がすべての原因のような気がします。(←これが言いたかった)

2006年から使っていたs225サーバが異常な高付加になっていたので、同じXrea内の新しいサーバに引越ししました。
その結果、嘘みたいにレスポンスが速くなりました。

今のところ大満足です。
ここ数ヶ月、サーバが遅すぎてブログ記事を書く気にならなかったのですが、これからはどんどん記事を投稿していけそうです。

話の経緯

Xreaのs225サーバのレスポンスがすごく遅くいことに気づく。
ブログやWikiのページ遷移に10秒異常かかる状態。

サーバ負荷観測所で負荷を見ると、何とロードアベレージが20以上!これはヤバイ。

カスタマーサポートに問い合わせて改善を要望したが返事なし。

もうXreaを卒業しようと、さくらインターネットや他のVPS業者を検討。

Serversman、Osukiniサーバなどに申し込んでみる。
申し込みが混雑しているらしく、音沙汰なし。

Xrea内の別サーバへ移管することを決心する。


最後の結論にいたるまでが長かった。。。反省。


サーバ移管のやり方

  • サーバ負荷情報を見て、負荷の低いサーバを探す
  • 無料サーバアカウントを新規で申し込む
  • 有料権限をその新規サーバに移管する
  • 旧サーバでDBをダンプする。
  • 新規サーバの管理画面でサーバ間コピーをする
  • ValueDomainのDNS管理画面で、ドメインと紐付くIPアドレスを旧→新サーバのIPアドレスに変更する
  • 新規サーバでドメインウェブの設定をする。(DNSが浸透する前に設定するとエラーが出て設定できないので注意)
  • 新規サーバでDBの復元をする
  • Pukiwikiなどでパーミッションエラーが出たらパーミッションを適切に変更する
  • MovableTypeで管理画面ログインしようとするとエラーが出るので、mt-config.cgiのDB接続情報を変更する(パスワード変更)


気をつけるポイントは下記のとおり。


  • サーバ間コピーは、コピー先のサーバの管理画面から行うこと(逆はできない)
  • サーバ間コピーは、無料→有料へコピーする(逆はできない)
  • サーバ間コピーでは、パーミッションは維持されるが、ファイルによってはオーナーが変わってしまうことがある。(apache → dqneoなどに変更される)。そのため、Pukiwikiでパーミッションエラーが出る。これは、コピー後にパーミッション設定を変更したら解決できた。

なお、旧・新サーバでのアカウント名を同じにしておくと移管が楽なのでオススメです。

参考にしたサイト
このサイトあのサイトこのサイトなんかで、デュアルモニターの快適性に書かれていたのを読んで、自分もいつかはとタイミングをねらっていました。
丁度、ずっと使ってきた三菱の17インチモニター(2001年末に6万円ほどで購入)がだんだんガタがきて、表示も暗いし色もときどき変になるしで、先月思い切って買い換えました。

デルの19インチワイドモニター(SE198WFP)を2つ。合わせて4万円。
注文確定をクリックするのに勇気が要りましたが、設備投資じゃーと自分に言い聞かせて注文クリック。
これが12/11ごろのこと。

さすがはDELLで、わずか3日後に家に届きました。
早速梱包を解いてセッティングと。
何も考えずにディスプレー2台をデスクトップPCにつなげようとしたら、アレ?
PC側には出力端子がオンボードのやつ1つしかない。

うぐぅ。

グラフィックカードを買わないといけないのね。。
すぐさまヤフオクで1500円のDVI出力ロープロファイルビデオカードを購入し、PCに装着。
よっしゃこれでデュアルディスプレイや!とディスプレイつないでみたら、何故かオンボードでつないだ方のディスプレイに映像が出ない。
この時点でPCにはマザーボードオンボードのDSUB出力端子が1個と、後から装着したグラボのDVI出力端子が1個あるわけですが、私はこれでデュアルディスプレイができると思い込んでいたわけです。
ところが、グラボとディスプレイをつないだ瞬間に、オンボードの方が表示されなくなる。

ちょっと調べてみたら、たいていのマザーボードはこういう仕様になっていて、グラボから映像出力するとオンボードの方が自動的に無効になるそうですね。

うぐぐぅ。。。

しょーがない。気を取り直して、カカクコムでデュアル出力対応のロープロファイルグラフィックカードを買う。玄人志向のGFX5200-LA18Cというやつ。4500円なり。
(結局、先ほど購入したグラボはお蔵入りにorz )

発送でかなり待たされて、やっと届いた新グラボをさっそく装着。
よく見たら片方がDVIで片方がDSUBなんですね。ちょっと残念。

気を取り直して接続。
ちゃんと2画面に映像が表示されました。
おーっと感動しようとしたが、よく見るとDVIから出力した方の映像がちょっとおかしい。
気持ち映像が横長に伸びて見えるし、文字が横につぶれてかすんで見える。DOS窓で字が読みにくい。
ウィドウを最大化すると横がちょっとだけ画面からはみ出す。

なんじゃこりゃ?
どう見てもモニタの解像度と出力映像の解像度があっていない。

しかしデスクトップのプロパティを見ても、ちゃんと解像度1440x900に設定されている。

うごごぉぐぅあおお~~~~

DELLのモニタが悪いのか、グラボのハードウェアの故障か、ドライバの不具合か、さっぱりわからん。。。いったい誰に文句を言えばいいのか?

とりあえず抱えているWEBサイト開発案件が手一杯だったので、不具合解決はいったんあきらめて、片方のディスプレイの映像がかすんだままプログラム開発を続行。
perlの文字化け問題(0x5C問題)と格闘しながら年が暮れる。

年が明けてちょっとスケジュールに余裕が出来たので、改めてこの「かすれ」問題に取り組む。

まず、DELLの不良かどうかを確かめるために、2台のディスプレイのDVIとDSUBを逆にしてみる。
お、今度もDVIでつないだ側がかすれて表示される。DSUBでつないだらきれいに表示される。
ということはモニタの以上ではないな。

次に、ドライバを疑ってみる。
天下のnVIDIAに限って、ドライバの不具合などないだろうとタカをくくっていたのだが、nVIDIAのサイトから最新のドライバをインストールしたらあっさり解決した。

あ、ドライバの不具合だったの。
なんてあっけない結末。

というわけで、かれこれ1ヵ月の格闘の末、やっとデュアルディスプレー環境が構築できました。

こんな感じです。
dual_monitor.JPG

めちゃめちゃ快適です。
作業効率が数十%向上するというのもあながち嘘ではないかも。

(ちょっと横の広さを持て余し気味ですがw)


というわけでみなさん、デュアルディスプレーにするときは、一筋縄でいかないことがあるのでよく調べてから環境構築をしましょう。


9ヶ月前に書いた記事の続き。

反省点

環境エラー

  • ローカル環境(windows)で作って、本番環境(linux)に移行した段階でエラー多発。
  • ブックマークが使えなくなって作業効率低下。
  • FTPアップロード忘れが多発して作業効率低下。
  • PHP.iniの設定が違うので挙動が変わり、作業効率低下。
     → 早い段階から本番環境で開発してればよかった。

ファイル命名規則の失敗

当初、confirm_form のように動詞_名詞方式でやっていたが、これがいけなかった。
ファイルを探すのにう~んと考える →作業効率低下・ストレス増大
form_confirmのように名詞_動詞方式でやっていれば、先頭の名詞をカテゴリラベル代わりに使えた。
→ phpのファイル名は、名詞_動詞.php 方式がよい。

ページ遷移図、ファイルリストの不備

実装を最優先にして、整理業務を怠ったために、どこに何があるか収集がつかなくなった。
そのため、後半に能率が大幅ダウン。
→ 最低限のドキュメントを、開発初期に作るべき。

いろんなファイルにコードを分散

いろんなphpファイルに、コードを書き散らして収集つかなくなった。
最初から、全ての関数をプロジェクト共通ファイルにまとめて書けばよかった。
個々のPHPファイルからは、それらの関数を呼び出すだけにするべき。
→関数を作る時点では、その関数を後で使いまわすかどうかは予測できない。
最初からライブラリに書くべき。

配列の使い方のルール

・二次元配列を多用して自爆
→ 二次元配列はなるべく使わないこと。 foreachループがネストして苦労する。

・配列の添字に0始まりと1始まりといろいろあって統一してなかった。
→ 配列の添え字は0始まりに統一すること。

関数の仕様を途中で変更して自爆

関数の戻り値を1次元配列→2次元配列に変更したら、これが原因で大量のエラー発生。
元の関数は保持したまま、新しい別の関数を作って徐々に移行すればよかった。

セッション変数はデフォルトでダンプすべき

良かった点

  • ieHTTPHeaderが超便利
  • クッキーの値を確認するのに役立った。
  • PHPはオンラインマニュアルが充実している
  • 定数を使ってページ先頭で遷移先を記述。define("NEXT","form.php"); これで可読性向上した。

無職3ヶ月目に突入しますたw

 

友人が独立して受託Web開発をやっているので、そこに弟子入りしました。

PHPを教えてもらいながら初めてWEBサイト開発をやりました。

弟子入りなので、無償ですw  (来月の家賃払えるのか>オレ)

 

延べ1ヶ月かけて、友人に助けてもらいながら小規模なWebサイトを作りました。

内容は、資格試験の自己採点サービスです。

 

最初の方は、PHPを勉強しながらさくさくスクリプトを書く感じで、スピードは遅いものの順調でした。

初期でつまづいたのはこれです。

 

セッション変数? $_SESSION ? 何それ?

 

「セッション変数」という、PerlにはないPHP独自のセッション管理機構を理解するのが難しかったです。


私のようなPerl初級プログラマは、クッキーしかしらないので、

「 は?セッション変数?何それ?

 HTTPにはステータス情報がないからクッキーでセッションIDをやりとりするのは知ってる。
 けど、セッション変数って何?クッキーのことじゃないの?」

というありさま(><)

 

結局、

「セッションIDに紐づくユーザの情報を、Apacheがメモリ上に保持してくれるので、ページ間で変数を共有できる」

ということだったようです。
いわゆるショッピングカートとかのあれですね。

これを理解するのに3日かかりました。

 

だってPerl/CGIには、Apacheのメモリ上にデータを保存するなんて発想はできないんですもの。

しかし覚えると便利ですね、$_SESSION。

根気よく教えてくれた友人に感謝。^^

このアーカイブについて

このページには、過去に書かれたブログ記事のうち活動記録カテゴリに属しているものが含まれています。

前のカテゴリはメモです。

次のカテゴリは読書メモです。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

Powered by Movable Type 5.02