エラー対応としてget_cookier関数をinit.cgiへ移動した。
再度新規投稿のアクセスログ出力への出力を確認する。
返信の確認
=== 修正の確認 ===
yybbs.cgiとinit.cgiとで共通にアクセスできるグローバル変数gMyCntを定義するのに四苦八苦してしまった。
同一ファイル(regist.cgi)では関数定義の外側にmy $xxx; と書けばどの関数からもアクセス可能なグローバル変数になるので、requireでincludeしているだけと思い同様にすれば可能と思ったがそうではなかった。
グローバル変数はパッケージ名を明示的に指定する必要があり $<package_name>::<var_name>とするようである。パッケージ名を省略した場合は$main::<var_name>となるとの事。
ただし定義側ではourを使ってもよい。
そこで試しに参照側もourを使ってみたところうまく動作した。
つまりinit.cgiの関数定義の外側で our $gMyCnt = 0; で定義し、yybbs.cgiの関数定義の外側で our $gMyCnt; と宣言すれば、両方のcgiの任意の箇所で単に$gMyCntで同一変数を参照できた。
文法的に正しいかどうかあまり自信がないが our は別名を定義するだけという説明が以下のサイトにあったので恐らくこれで正しいように思われる。
Perlの組み込み関数 our の翻訳
https://perldoc.jp/func/our
ということは require は単にincludeではなくどちらかというとコンパイル後のobjをつなぐものかもしれない。そして our は EXTERNAL宣言に近くアドレス解決を他モジュールでやれという指示なのかもしれない。
>そして our は EXTERNAL宣言に近くアドレス解決を他モジュールでやれという指示なのかもしれない。
==> 最初に出現した場所で領域が確保され、後続の our 宣言では既存の領域を参照するようにアドレス解決する。ということなのでしょうね。
以下のサイトを見つけた。
requireは動的リンクのようである。
[技術継承の現場] useとrequireの違い
http://www.ndis.co.jp/blog/tech/2008/10/use-require.html
うーん、スクリプト言語に動的リンクがあるとは驚きでした。高級ではあるがスパゲッティを生みやすい仕様ですね。
現在日時を取得するための専用関数は作らずに
$ENV{TZ} = "JST-9";
my $my_time = time;
my ($my_cur_day, $my_cur_time) = my_unixtime_to_daytime($my_time);
としたが、エラーメッセージの多くに現在日時を追加したため上記3行をあちこちにコーディングしてしまった。
==> やはり専用関数があったほうがよかった。まずはアクセスログ処理について修正しよう。
アクセスログファイルを見るとIPアドレスが変化しているにも関わらずカウンタ値が変化しないケースが稀にある。
==> 原因は恐らく&mode=xxxでxxxに不正値が設定されてyybbs.cgiが起動されているものと思われる。modeがヌルでなければカウントファイルは更新されないというロジックになっていた!
==> bbs_list関数はそもそもmodeを参照しないためこのロジックの意図は不明。いずれにせよ、そういう起動をしているクライアントがいるということは認識しておきたい。
==> アクセスログには&name=valueで指定され得る値も記録するようにしよう。
現在はカウントファイルのアクセス後にアクセスログファイルをアクセスしているためデッドロックは発生しない。アクセスログファイルをregist.cgiからも更新するようにするとregist.cgiではカウントファイルをアクセスしていないためアクセスログファイルの処理の中でカウントファイルをreadすることになるが、ここでファイル・アクセスの入れ子構造を作ってしまうと実装にもよるが自端末のyybbs.cgiプロセスと別端末のregist.cgiプロセスとがデッドロックを発生させてしまう可能性がある。
==> カウントファイルの内容はグローバル変数に置きyybbs.cgiはそれをアクセスする。regist.cgiも初期値ゼロが設定されているそのグローバル変数をアクセスする。regist.cgiによるアクセスログであることは判別できるようにする予定なのでカウント値がゼロでも問題ないであろう。
更新日時の時刻は時分だったが秒を追加した。
既存のものはそのまま。新規投稿分より反映されるはず。
表示順等の他の処理に影響するかと思ってやらないでいたが、特に影響はないようなので実装することにした。
返信でも反映されるか確認する。
===修正===
修正日時に更新されることを確認する。
過去ログへは通常表示(スレッド画面)と一覧表示(トピック画面)の各ページから遷移できるが、過去ログの「戻る」では常に1ページ目に戻っていた。これを修正し元のページに戻るようにした。
==> うすうすは感じていたがこれだけのためにこのようなややこしい修正が必要になるとはWebシステムの基本的な欠陥を再認識した。クライアント側で状態を持つのは容易ではない。過去ログ側でファイル番号やページを変えて画面遷移する場合、<form>で画面が変わる場合はhidden属性の<input>で引き継いでいく。<a>で変わる場合は&name=valueの形で引き継いでいく。各画面では何にも使われないが最後に戻る際にのみその引き継いだ値を使って元の画面(通常表示か一覧表示)の元のページに戻るわけである。
クライアイント/サーバ型システムであればクライアント側にプログラムを持つため状態を設けることは容易であり上記のような隠し属性をずっと引き継いでいくようなことはせずに実装できるはずである。
Webシステムが大規模かつ複雑化していくということは巨大なスパゲッティ構造がどんどん肥大化していくことを意味し将来誰も保守できないといった悲惨な状況を招きかねない。