すみません (13:46)
操作ミスでインデックスをぶっ壊してしまいました。修復の間サーバーとめます。問題なければ10分くらいで戻ると思います。
やっぱり時間がかかりそうです
簡易修復で大丈夫かと思ったんですが、動かしたらやっぱり問題が残っていたんで、完全修復かけます。しばらくお待ちください。
CO
ちなみに何をやっちゃったかというと、PhpMyAdminで巨大なテーブルのテキストカラムのTアイコンを間違ってクリック(というか通りすがりにマウスボタン押下)してしまったんですよ。インデックス作成ボタンも、他の破壊的な機能を呼び出すボタンと同様に、alertくらい出せよ!(逆ギレ) っつーかインデックス作成が1クリックでできるインターフェースなんていらないよなー。
データとテンプレートの配置 その3 (21:47)
実際にサンプルコードを書いてみたところ、このアプローチって設計・コーディングが面倒くさい割には実際のメリットはさほど大きくない気がしてきた。どうしてもサーバーサイドでのテンプレートを主にしたければ、JavaScriptでもサーバーサイドで展開された結果をそのまま利用した方が手っ取り早いかも。
Ajaxにおいては、クライアントが必要なデータをサーバーから直接(HTMLパースとかせずに)取得できるということが重要なのであって、それをどのような仕組みで対人間向けのフォーマットに変換するかはさほど重要ではない。あるいは、その仕組みの部分の汎用性に凝ることのメリットはそれほど大きくない。
そこでテンプレート展開以降についてはこだわらず、データ取得以前の部分にだけこだわって、次のような方針を考えてみた。
- まず基本的な内部設計として、サーバーサイドのデータ取得ロジックは、APIとして公開することを意識したインターフェース設計にする(多少冗長でも)
- インターフェース設計のポリシーとして、http://example.com/path/to/resourceで通常のブラウザ向けのHTMLが得られる場合
- http://example.com/path/to/resource?__mode=rdfでRDF(XML)形式のデータが得られる
- http://example.com/path/to/resource?__mode=jsonでJSON(JavaScriptコード)形式のデータが得られる
- http://example.com/path/to/resource?__mode=htmlで部品利用向けのHTML形式のデータが得られる
なんて感じでどうだろう。
最後の部品利用向けHTML形式のデータというのが、サーバーサイドでテンプレート展開したデータをそのままJavaScript側で利用するパターン。JavaScriptで複雑なデザインを組み込む・メンテするのが面倒な場合はこれで対応。逆にJavaScriptコードからの操作性を向上させたい場合は2番目のJSON形式を主に利用。RDFは汎用あるいはRSSリーダー(RSS 1.0互換)用って感じ。
なんて感じでデータの読み込み側はそれなりにきれいに表現できるかなーと思いつつも、もうちょっといじっていたらまた気が変わるかもしれない。
ちなみに現在迷っているのはデータの書き込み側の仕組み。読み込みと同様にブラウザ向けHTMLと同じURIに対して、?__mode=jsonとかつけて渡す(POSTする)と、書き込み結果(成功・失敗。あるいはもっと詳細なエラー情報など)がJSON形式で返るようにしようかと思ったりもしたんだけど、ブラウザからの書き込みの場合は結果が文字列で返されるパターンよりも、結果に応じてリダイレクトしたりするパターンの方が多そうなんだよな。基本的な挙動が違う処理を呼ぶのに同じURIを使うのは直観的じゃない気もしてきた。書き込み系処理に関しては、API専用URIを別に割り当てた方がいいのかな?
データとテンプレートの配置 その2 (15:12)
「データとテンプレートの配置」の続き。
サーバーサイドメインで行く場合のアプローチとしては、挫折するまではこの間書いた方向で試してみようと思ってはいるんだけど、
んだけど実際作ってみた感じ、オレにとっては最善の選択肢ではなく、createElementなどでがりがりDOM弄った方が楽だった
http://subtech.g.hatena.ne.jp/secondlife/20051129/1133228965
という記述を読んで、さらに具体的なイメージを考えてみた。
自前でcreateElementするようなアプローチでは、新しく生成した画面要素オブジェクトを、そのまま変数に入れてロジックで管理できる。だから、動的に構成した画面要素の管理がわかりやすく書ける。というのが、上記の体験談の骨子なのではなかろうか。
サーバーサイド、クライアントサイドに限らず、テンプレートによってHTML展開するような構造の場合は、生成された画面要素にロジックからアクセスしたい時に、そのオブジェクトへの参照を得るためには手間がかかる。具体的にはidやnameを使って解決したり、あるいはDOMツリーを順次たどって目的のオブジェクトを取得する必要がある。各手段のうち、idでの解決方法ならばシンプルに書けるが、それ以外の方法で解決するのは面倒だ。
逆に言うと、テンプレートによるHTML展開を使った場合でも、必要なオブジェクトに対して簡単にアクセスできるような方法が用意されていれば、十分に楽だと感じられるのではないだろうか。
ぱっと思いつくアプローチは2つ。
- テンプレート展開する要素に何らかのルールに基づくidを割り振り、idベースでオブジェクトへの参照を解決する
- テンプレート展開する際に、単にHTML文字列として展開するのではなく、DOMオブジェクトを返すJavaScriptコードとして展開する
前者の場合は、id命名のルールとして実用的なものを考える必要があるだろう。現時点ではあまりいい方法を思いつけていない。後者の場合は、テンプレート展開処理がとても面倒くさくなりそうだ。単に外側をdivで囲うだけでいいなら簡単だけど。
ともかく、サーバーとクライアントで共通のテンプレートを利用するという方針に加えて、テンプレート展開した画面要素に対して、JavaScriptコードから簡単にオブジェクトとしてアクセスできるようにする、という方針も考慮するようにしよう。
とかのんびり考えていられる時間は今日でおしまいなんだけどね。
ただいまサービス停止中 (05:25)
DB最適化作業中につきサービス停止中。1時間程度で復帰する予定です。というか間違って寝ちゃいそうだから、1時間後に自動復帰するようにしておくか。
思ったよりも時間がかかっているんで
リスタート予定を08:00に延期。
まだ終わらない
どうも08:00には間に合わないっぽいんで、再開時間を09:00に延期します。それにしても時間がかかるなー。
うわー、すみません
なんか見積もりが全然あってない。まだ終わりそうもないんで、再開時間は10:00に延期します。おかしいなー。他の同サイズのテーブルはこんなに時間がかからなかったのに。激しく断片化されたvarchar(255)のuniqueインデックスみたいなものがあるとさすがに時間がかかるのかなー。
さらに、すみません
残り400Mバイトまで来て処理速度が大幅に落ちてしまい、10:00にも間に合わなそうです。11:00に延期します。くそー、こんなことなら早朝じゃなくて深夜帯に作業するんだったなー。
データとテンプレートの配置 (15:16)
ちょっと暇(というか仕事がぐだぐだになってきたんで、いったん調整のためにサスペンド)ができたんで、Ajax関連のことを考える時間に使ってみることにした。
Ajaxの具体的な使い方は、もちろん各機能要素のスペックが許す範囲でいろいろあり得るわけだけど、基本的な方針としてどういう使い方をメインにするべきだろう。
Ajaxのできることというと、結局のところ、
- サーバーからデータを取得し、
- JavaScriptのロジックで使用する(XML、JASON、その他)
- 画面要素(HTML、DOM、その他)として使用する
になるんだろうけど、その後者のパターンにおいては、どういうやり方が一番いいんだろう。具体的にはテンプレートをどこに置くのが一番スマートなんだろう。
俺は基本的にサーバーサイドメインで考えるから、画面要素を取得する場合には、HTMLレベルまでサーバーサイドで展開してしまう方が好みだ。JavaScriptのテンプレートライブラリとかも使ってみたけど、いまいちしっくりこなかった。
ただ、Ajax(というか今後のJavaScriptを多用したアプリケーション)のメリットの一つである、UIに関するクライアントサイドでの自由度を低めてしまうのは、もしかしたらあまりよろしくないのかなーとも思ってしまう。
自分1人の問題ならば、どうせ何かあったらサーバーサイドいじっちゃうからいいんだけど、一般ユーザーがクライアントサイドでカスタムできる可能性ってのは、Ajax(もしくはJavaScriptベースのアプリ)の世界においてはそう簡単に捨ててはいけない要素のような気がする。
でもやっぱりJavaScript側でテンプレートを持つのはいやだなー。
と書いているうちに、何となく次のような設計にすればいいんじゃないかと思いついた。
- 基本的にはサーバーサイドにテンプレートを持つ。サーバーサイドで処理をする場合はそれを使ってテンプレート展開する。
- JavaScriptサイドでは、以下の3つのメソッドを用意する。
- サーバーからデータを取得するメソッド
- サーバーからテンプレートを取得するメソッド(このテンプレートは、サーバーサイドで持っているテンプレートデータから生成する)
- テンプレートにデータを適用するメソッド
結局JavaScript側にテンプレートライブラリを持つわけだけど、JavaScriptで独立したものにはせず、データはサーバーと共用できるようにしておく。そうやっておくことで、同じHTMLをサーバーサイドで生成する場合もクライアントサイドで生成する場合も、テンプレートデータ自体は同じものを利用できる。クライアント側でテンプレート取得回りのロジックをいじればUI変更とかもできる。もちろんデータ取得メソッドは独立して利用できる。
すでにそういう方針で作られた(できればPHPの)ライブラリとかフレームワークはないかなー。
俺的に一番まっとうなアプローチは
SmartyのJavaScript用コンパイラ(データと同じスコープでevalすると、そのデータを使ってHTML展開された結果を返すようなJavaScriptコードを生成する)を書くことなんだろうなー。テンプレートデータの構文解析自体はPHP用のものをそのまま使えるだろうから、あとは各構文ごとの展開処理をJavaScript用に差し替えていけばいいのか。完全互換は難しいだろうけど、主要な構文だけだったら何とかなるかなー。さわりだけ試してみて、本格的に手を出す価値があるかどうかを検討しよう。
evalのスコープは
PHPとは違ってJavaScriptは未宣言の変数がグローバルスコープになっちゃうから、PHP互換でコンパイルした後に利用変数を頭に戻ってローカルスコープで宣言し直す必要がありそう? JavaScriptのevalってどういうスコープで実行されるんだろう? evalが実行される場所のスコープになるんだよね、きっと。
ゴミ処理プロセス終わらんなー (14:34)
DBのゴミ掃除がなかなか終わらんなー。すでに3Gバイトくらい削除したんだけど、まだ1Gくらいはゴミが残っていそうだ。
当初の予定ではデータがあふれそうになる前に、mergeテーブルを使った設計に切り替えて、重要度の低い(=自動収集したがどこも参照していない&どこからも参照されていない)データも残していこうかと思っていたんだけど、そんな設計変更をしている余裕がないし、CPU/メモリリソース的にも厳しいんで、ある程度古くて重要度の低いデータはばしばし消していく方針に変更。テクノラティあたりなら余裕で全データ保持しているだろうし、うちで取っておく必要はないだろう。
というわけで、今週になってもまだ全体的にサービスが重いです。さすがに全部で1億レコード近くなると結構時間がかかるなー。表側のサービスを動かしながらじゃなければ、1日程度で終わりそうだけど。
カーテンと加湿器とエアコンを買った (12:17)
さらに風邪対策として、厚手のカーテンと大型の加湿器と寝室用のエアコンを買った。薄手のカーテンだと窓のそばがしんしんと冷えるようになってきたし。あと、もともとスチーム式の加湿器はあったんだけど、それとは別にリビング用に大型の気化式加湿器を追加。サンヨーの洗濯機を買ったばかりだし、サンヨーつぶれず頑張れということでサンヨー製品を選択。さらに寝室用の安いエアコンも買ったんだけど、加湿器で湿度を上げておくと体感温度がずいぶんあがるんで、寝室用のエアコンまではいらなかったかもなー。ちなみにこっちもサンヨー製品だったけど値段と暖房のパワー(W数)だけで選んだんで製品名は覚えてないや。今月は子供の風邪でずいぶんひどい目にあった(まるまる一週間休まされた)んで、さらに痛い目に遭う前にできるだけの対策は取っておこう。
インフルエンザの予防接種を受けてきた (12:06)
土曜日に家族全員で。今年はやばそうだから。でも子供は2回に分けて受けなきゃいけないんだっけ。3週間後にもう一回行かないと。ちなみに3000円だった。
うわ、やられた!? (10:28)
クレジットカードの明細を見たら、身に覚えのないリボルビング払いの請求が混ざっていた。項目がAmazonになっているから、てっきり自分で買ったものだと思っていたんだけど、今まで一度もリボルビング払いでなんて買い物してねーよ。なんだよこれ。
カード利用状況を過去にさかのぼって(カード会社のオンラインサービスを使うと過去のもまとめてみられる)調べてみたら、なんか6月くらいからそういうものが混ざっている。しかも、項目名にわけのわからない記号(「 - ( 」なんて感じ)が書かれた項目まである。
うわー、もしかしてどこかのオンラインショップとかからカード番号が漏れたか! 1万円以下程度の買物を、リボルビング払いで分割に均されちゃうと、俺みたいに細かい金計算していないやつは気付けねーってばよ。俺ってば半年もクレジットカード盗用されて、全然気づいていなかったマヌケですか!
あわててカード会社に電話したところ、
- 俺の契約カードでは、海外決済(Amazon.co.jpも海外決済扱い)が自動的にリボルビング払い扱いになるように設定されていた。つまり、今までAmazonで買ったものがリボルビング払い枠にためられていただけ。
- 変な記号の項目は、単にネット閲覧用のPDFに変換するときの文字化けで、紙に印刷した明細ではきちんとした(身に覚えのある)請求元だった。
ということでしたとさ。ひとまず紛らわしいんで、今後は海外決済も通常の支払方法をとるようにしてもらった。過去の分も一括払いに変更してもらえる(=リボルビング手数料・利子を取られない)らしいけど、手続きが面倒だからまあいいや。そういや6月くらいにAmazon登録カードを今のカードに換えたんだっけ。
都内の河原にカブトムシの幼虫がわらわらいた (14:54)
昨日は昼過ぎからうちの野球チームの最終戦を見物し(俺は子連れだったんで参加できず)に行った。荒川の土手のグラウンドだったんだけど、ムスコが虫取り網を持っていたのを見た、グラウンドの管理人のおっちゃんが、そこらの枯れ草の山の下からカブトムシの幼虫をわらわら掘り出して、ムスコに10匹くらいくれた。都内の河原になんてカブトムシの幼虫がいるもんなのか。ちなみにうちにはもともと、今年飼っていたカブトムシが産んだタマゴから孵した幼虫が5匹いたんだけど、新しくもらった幼虫はもともといたやつらの半分くらいの大きさしかなかったのは、やっぱり自然環境の方が成長に厳しいからかな? それとも単に生まれたタイミングの違い? ともかく今家にあるケースには多すぎるくらいの数に増えてしまったんで、このままにしておくと何匹か死んじゃいそうだ。子供の保育園にでも半分もらってもらおうかなー。