明らかに状況が変わってきている今日のプログラミングとは?

増6.「単一代入」考

»

●今回の発端

 「自転車とプログラミングと」の、「7.最後に」で、“ある範囲内では何度でも代入でき、その範囲を超えたら(あるいは超えたことを示す単一代入の属性をセットしたら)、絶対にいじれない”ように緩和された「単一代入」が有ったらいいという趣旨の発言をしました。

 2~3、指摘も受けましたが、自分なりの理屈はあったのです。

 今回は、それについて弁明します。

●「単一代入」

 筆者の若かりし頃、「人工知能」だとか「第五世代コンピュータ」だとかが人口に膾炙していた時期がありました。

 そこで使われていた言語にPrologというのがあり、“変数は一度作ったら値を二度と変えられない”という特徴がありました。

 現在でも、言語によっては(文字列型などで)その様な仕組みのあるものもあるとは思いますが、Prologはもっと徹底していて、変数への参照の変数がなく、.Netなどで当たり前にできる、

 a String
 a ←(参照を代入) new String("foo") -(1)
 a ←(参照を代入) new String("bar") -(2)
((1)で作った"foo"は、(2)では壊され新たに"bar"が作られる。変数の参照への変数は何度でも変えられる)

のといったなこともできませんでした。

●理屈の背景

 筆者は、PHPでホームページを作っています。他の言語は知らないのでここではPHP5.3限定で、ホームページを作る際の問題について書きます。

PHP5.3は、

  • グローバル変数(スカラー変数、オブジェクト変数への参照)の生存期間が「そのページ限り」で、それを超えた生存期間が必要な場合、セッション変数を使います。
  • セッション変数には、オブジェクト変数への参照をセットできません。
  • シリアライズすれば、オブジェクト変数をセッション変数にセットできます。

という制限があります。

 筆者は3番目の「シリアライズ」とを知りませんでした。馬鹿ですが、残念ながら事実です。つまり、画面限りでない変数はすべて、スカラー変数としていました。

あと、ここで言うPHPのホームページは、ボタンなどを押すと必ず画面遷移する形式のもので、新式の「ページを固定して、innerHTMLを順次書き換える」ものではありませんでした。

●その結果なにが起こったか

 まさに混沌です。

●なにかできないか

 オブジェクト/クラスによる整理ができず(本当はできたのですが、しませんでした)、パッケージ的なまとめ上げる言語機能も知らない状況で(自分だけ知らないのかもしれませんが、PHP5.3にはなかったように思います)できることを考えました。

  • 個々のセッション変数は、特定の画面PHPファイル、機能PHPファイル内でのみ変更し、他では変更しない。

という規範です。それを担保するために、

  • セッション変数のキー(変数名)に接頭語をつけ、どの画面/機能が“本籍地”か

を区別しました。“本籍地”以外では値を参照するだけにとどめます。

 言語・機構等で強制できない、単なる規範ですが、特定の画面/機能ファイル内を観測できない存在から見ると、雰囲気「単一代入」に見えなくないと思います。

●よかったこと

 ボタンを押すたび画面遷移する形式のPHPでは、ブラウザの「戻るボタン」が大敵です。一度通った画面をブラウザの「戻るボタン」で戻られると、戻った先の画面ではキャッシュされた画面情報が表示され、PHPの機能が実行されることはなく、

  • 画面1でセッション変数1の値に1をセット
  • 画面2に遷移
  • 画面2でセッション変数1の値に2をセット
  • ブラウザの戻るボタンで画面1に遷移
  • 画面1でセッション変数1に2が入っている

というシナリオで、もし画面1でセッション変数1に2が入っていると問題になる場合、困ってしまいます。

たとえ、画面2上に“PHPで管理している「戻るボタン」”が存在し、そのボタンを押下すると

  • セッション変数1を1に戻してから画面1に遷移

の意図だったとしても、ブラウザの「戻るボタン」によって、その処理は無視されてしまいます。
(jQueryのReadyイベント(ブラウザの「戻るボタン」でも起きる)でも使って、AjaxでPHPの所定の機能をキックすればいいかもしれませんが、そのようなことは当時思いつきませんでした。)

それが、今回の「単一代入」では起きなくなるのです(画面2でセッション変数1に値をセットする事は禁止だからです)。ブラウザの戻るボタンは単純に考えると、Prologのバックトラックと似ている点があると思います。ですので、Prologで取り入れられた「単一代入」が、PHPでも(いくらかでも)寄与するのだと思います。

●オブジェクト/クラスなら解決か?

 オブジェクト/クラスを使うと、特定の値の保持や操作をその中に集中して納めることができ、上記の様な問題はなくなると思われがちです。しかしながら、オブジェクト/クラスであっても、

  • 状態を更新するメソッドを(複数の画面などで)制限なしに利用する

ならば、結局、混沌になると思います。

 オブジェクト/クラスにしただけでは、値や操作を1つの場所にまとめることはできても、その利用をまとめたことにはならないのです。

 値や操作の利用までを簡単に管理する常套手段として、ReadOnlyでない部分に着目する方法がありますが(RDBの分野でのCRUD図など)、もっとも単純な(よりきつい規範として)「単一代入」はよい方法の1つだと思います(後知恵ですが、「シリアライズできるのは“本籍地”の画面/機能PHPファイルのみとし、シリアライズするまでのオブジェクトは何度も更新するが、一度シリアライズしたオブジェクトは二度と更新しない」と言ったやり方もあるかと思います。)。

 「7.最後に」で筆者の念頭にあったのはこういうことでした。と筆者は弁明します。

 まぁ、今回はこんな所です。

●コラムのコメント欄の方針

 コメントに対し、当意即妙の回答を、それなりのタイミングでする自信がありません。

 ですので、このコラムで、

 ・わたしは基本的にコメントに答えない
 ・コメントを書く人は、回答がない前提で議論を進めていただく

とさせていただきます。

Comment(0)

コメント

コメントを投稿する