Mimir Yokohamaに「いいね機能」「コメント機能」を追加

概要

Weekly 10000PVを達成して機能強化に力の入っているMimir Yokohamaのウェブサイト。

連続の機能強化でついに「いいね機能」と「コメント機能」が追加された。

実は先日の「お問い合わせフォームの実装」は単にその機能を実装する最小限ではなく、簡単なアプリケーションを実装できるプラットフォームになっており、 アプリケーションを追加する条件が整っていたのだ。 また、そのためのテストもしてあった。

そのため、実は今回コード追加はわずかで、両方合わせても23行ほどにとどまる。 ごく簡単だが、確証が持てないためにテストと本番環境のための修正を行ったりして結構な時間がかかった。

これに関してはみるべきところはあまりない。 受け取ったパラメータをファイルに書き込めば良いだけだからだ。

ちなみに、連打しやすいアプリケーションを入れるために連打の対策もサーバーにしてあった。 実は先のパフォーマンスチューニングはこの対策によってパフォーマンスが低下してしまったため、これをカバーするついでに行ったものだった。

いいね機能の設計

いいね機能はごくシンプルだ。

Pandocテンプレートを使ってページタイトルを埋め込むことができるので、これだけ使うのであれば単にテンプレートの中にフォームを書けばいいだけ、ということになる。

実際はリファラ(Rack::Request#referer)及びユーザーエージェント(Rack::Request#user_agent), IPアドレス(Rack::Request#ip)も特定に使用している。

ポイントは「一度送信したら表示を変更、送信を無効化する」ということだ。

inputタグのdisabled属性を使うことで送信ボタンを無効化している。

そう、この機能はHTML上でインラインで書かれているのだ。 このような書き方はW3C的には推奨されないのだが、Googleは推奨している。 実際、これだけのためにJavaScriptファイルをロードさせることをしたくなかったので、インラインにした。

ポイントは

  • Legacy DOMにおいてフォーム部品は連想配列のようにアクセスできるようになっている
  • submitボタンのラベルはvalueである
  • disabledによってフォーム部品を無効化できる

である。

これらの処理は送信の「前に」行われる。 これは正しいことではないが、問題はない。 なぜならば

  • 送信できなかったからといってユーザーが修正するなどの手を入れる余地はない
  • 特に返信を必要とするものでもないので、送信失敗はクリティカルな問題でもない
  • サーバーエラーなどは表示されるようになっている

からだ。

また、画面変遷せずに送るだけ…というと、Ajaxで非同期に送るしかないように考えるかもしれないが、 実際は現代のブラウザは基本的に2XXステータスで空コンテンツを返すとページ変遷しないようになっている。

このような用途のために204(No Content)が用意されているため、204を返す仕様だ。 できるだけブラウザの標準機能に頼るようにしている。

このボタン、めっちゃgooglebotが押してくる…

コメント機能の設計

公開されるものではなく、sanitizeしなくても問題が発生しない設計になっている(単に文字列として扱う以上の取り扱いがなされる条件で使用しない)ため、非常に楽だ。

難しく考えるよりも、シンプルで挙動をちゃんと把握できていて、余計なことをしない方法をとるのが最も楽に、確実に、バグなく設計できる。

ただ、この機能に関しては「コメントフォームの表示」などが必要になり、JavaScriptが必要になった。 また、コメントするというあまりとらない行為のための部品であり、常にロードすることは非常に好ましくない。

そこでとった方法は「JavaScriptの遅延ロード」であり、「クリック時にelementを追加してJavaScriptを読み込む」という方法だ。

これでscript要素を追加している。

では呼び出されたあとどうしているのか…というと、こんな感じだ。

そう、コメントフォームは標準でHTMLに含まれていない。

パフォーマンス的にみても親切機能のためにもう重くなりつつあるドキュメントをこれ以上重くしたくないので、 「フォーム部分はJavaScriptがロードされたときにinnerHTMLで書く、という方法をとっている。

「クリックされたときにはじめて必要とされるのでドキュメントノードを追加してロードする」という手法は稀に使われるが、さすがにそれでHTMLドキュメントそのものを生成するというのはまず見ない手法になっている。

連打されたときのことを考えて、clickイベントを発生する値に特殊なプロパティを埋め込み、何度も実行されないようにしている。 なお、これは本当に連打したときだけ機能するもので、JavaScriptシングルスレッドなので一回このスクリプトに入っていまえばこのスクリプト中に割り込まれることはない。 だが、連打されるとイベントがキューに入ってしまうので何度も実行されてしまうことから、そうしたことがないようにしている。 シングルスレッドなので、このスクリプトが実行されているのにプロパティが設定されないうちにまた実行されるということはない。

元になるフォーム自体は存在していて、submitボタンを配置すればフォームの送信は可能だ。 そのため、submitイベントに対するイベントリスナーを設定するものはHTML上に静的に存在している。

その上で「フォームはやっぱり閉じられたほうがいいな」ということでボタンクリックに対するイベントの変更、及びボタンラベルの変更を行っている。

送信を行った場合はもうコメントフォームは使わないので、コメントフォームは非表示にして(削除はしていない)ラベルを変更している。

ラベル変更だが、input部品とは違ってbutton要素は子要素テキストノードがラベルになっているので、dataプロパティの書き換えによって変更している。

もともとHTML上でLevel0 DOMイベントを使っているので、スクリプト上でもLevel0 DOMによってイベントを変更している。 いつもaddEventListenerを使っていたので、珍しい。 イベントの削除はイベントにnullを代入するだけだ。

なお、HTMLで全て含めてしまえばJavaScriptは排除できるのだが、これ以上余計な要素を組み込むことはできれば避けたいためこのような仕様になっている。既にDOMコンパイルは割と重い。

また、デザインポリシーからいって、多くの場合余計なコメントフォームを常に表示させておくというのは美しくないとも思っている。 JavaScriptを使わずCSSでオンオフするようにもできるが、そうすると今度はボタンのテキストを変更するのが難しいし、連打や再送信を防ぐのも難しい。

このことから、なにがなんでもJavaScriptを使わないのが正義、ということでなければ、 このような付加コンテンツはユーザービリティの点からも素直に使うべきだと思う。

こちらもいいね機能同様、送信する前に状態を変更してしまい、成功すれば204を返す仕様。

Legacy DOM と DOM Level0 Eventに関して

Legacy DOMやDOM Level0 Eventについて意見をもとめられることがたまにあるのだが、私としてはあまり勧められないと考えている。

非常に簡単なので学習にはいいが、Legacy DOMはHTMLの構造に依存する。例えば

として、

とかやってしまうと、ドキュメントの構造が変わるたびに修正だ。

だが、「フォームにのみnameで使い」「フォームはW3C DOMで特定する」のであれば悪くない。

DOM Level0 Eventはイベントリスナーが1つしか登録できないためモジュール設計になっている場合や、なんらかのライブラリを使っている場合は使ってはいけない。 イベントを「追加」する場合はLevel2で、イベントを「設定」する場合はLevel0という使い分けも考えられる。 HTMLに直接書く場合はLevel0しか書けないので、その部品の基本的な動作と定義されているならLevel0でもいい。

ただし、その場合でもできればLevel2 Eventを「後から追加する」のが適切なので、DOM Level0 Eventの使いどころは今回のようなものが唯一だと思う。

Amazonのコンテンツ戦略とユーザーの問題

かつてのPrime

Amazonはいよいよ本格的にコンテンツ課金をはじめたようだ。

Amazonはプライムの価値を高めるため、Amazon Prime Music, Amazon Prime Photo, Amazon Prime Videoといったサービスをはじめた。 このサービス自体はアメリカ(.com)と同じものだが、.comと比べるとだいぶ安価な設定になっている。

そのためにプライムの価値は高かった。 当時プライムでなくても配送は無料だったし、お急ぎ便と変わらないスピードで届いていたのでプライムの価値は微妙だったけれど、こうしたコンテンツの充実によってプライムの価値を高めた。

Prime Musicはもとより微妙だった。 音楽大好きな私は大歓迎したのだけれど、とにかく収録曲数が少ない、というかラインナップが大変微妙。 しかもその微妙な音楽もどんどんPrimeから外されていくので実用性も微妙だった。

特殊なBGMをかけたいとき(ムードミュージックとか)でなければ使わなかった。

Prime Photoは現在も有効だけれど、写真をAmazonに渡すことを考えると…

そうしたことを踏まえてもAmazon PrimeのキラーコンテンツはAmazon Prime Videoだったと言っていい。

コンテンツ課金へ

付加コンテンツは微妙だが本国より圧倒的に安価なAmazon Primeはかなりの人気を集めた。

だが、Amazonはあまりユーザーのほうを向いていないようだ。

非Primeに対して送料有料にする、ということは無料自体が一時的なものだったからやむを得ないだろう。 また、梱包の質が落ちていることも、配送が遅れ気味であることも、Amazonのサービスの根幹的価値を落としている気がするが、かつての品質が非人道的労働によるものだとするならば、人はその品質低下は受け入れるべきだろう。

だが、問題は結局はPrimeに付加コンテンツを含めることをやめつつある、ということだ。

今後追加されると言っていたPrime Musicに関しては追加された楽曲にめぼしいものは少なく、主には(.comでライセンスされている)洋楽だった。むしろ追加より削除のほうが目立ったくらいで、人気アーティストの盤はライブや 結局、(私に限らず)Amazon Prime Musicは おまけのような存在を脱していなかったのだ1

そこへAmazon Music Unlimitedが追加された。Music Unlimitedサービスとしては標準的で、Primeサービスを拡張する感覚で使えるのがメリットだ。 だが、Amazonの付加コンテンツがただのお試し版であることが明らかになってしまったとも言える。 Primeの価値を高めるために追加されてきたコンテンツはあくまで他の有料サービスの体験版で、Primeの価値を高めるものではない(広告的存在である)と位置づけが変わってしまい、結果的にPrimeの価値はさらに下がった2

そしてPrime Videoもいまいちな状態となり3、早々にPrimeのみの表示だったトップページがPrimeをクリックしてもAmazonビデオのトップページとなり、さらに現在はPrimeのページにも購入の項目が並ぶようになっている。

そして有料チャンネルの追加だ。Prime VideoからJ-Sportが見られるようになった、というメリットはあるものの、これも本家で入ったほうが安く、オプションも豊富、見られる番組も多い。

とはいえこの時点では従来のPrime Videoが損なわれたわけではなく、「微妙な有料追加コンテンツが入った」というだけなのであまり見向きもされなかったのだが、一気に話題となったのがdアニメ for Amazon Primeの登場だろう。

Amazon Prime Videoはもとより比較的アニメに強かった。 だが、dアニメが圧倒的なラインナップを誇るためアニメ好きの選択肢というよりはアニメファンとしてはライト層の選択肢であったといっていいだろう。 ここにdアニメが加わったことは、単純に言えばAmazon Music Unlimitedのようなもので、コンテンツに幅が増えた、と言える。

だが、問題は、本家dアニメと比べて随分とラインナップが少ないこと、そして「Amazon Prime Videoを廃止してdアニメのみになった人気番組がある」ことだ。

ユーザーの絶望的リテラシー

もちろん、そのようなことは腹立たしいだろう。 私も「えー」と思った。

だが、大荒れのレビューは、ちょっとこんなにも愚かな人がこの世界にあふれているとはにわかには信じがたいものになっている。

まず、「元々お金をとっているのにさらに追加でお金をとるなんて詐欺だ」という主旨の発言。

Prime Video以外に選択肢がある、と理解しているのであればPrime経由でなくそちらでみればいい。 別に複数の課金コンテンツがあることはなんら問題ないだろう。 また、(その人はアニメのためにPrimeに加入しているのかもしれないが)Amazon PrimeはそもそもAmazonでの買い物のための優待であって、Prime Videoは付加コンテンツにすぎない。Amazon Primeが気に入らないのならPrimeを退会すれば良いし、なんならAmazonを使わなければ良い。 その自由はあるし、別にAmazon Primeをやめて他のところに加入するのも、Amazon Primeとは別に他のところに加入するのも自由だ。 Amazonにお金を払っているからといってすべてが手に入るわけではないのだから。

そして、「Primeのマークがあるのに途中からdアニメに課金させるなんて詐欺だ」という主旨の発言。

実際にそのような作品があった(それもかなり有名所であった)ため気持ちはわからないのではないのだが、元々Amazon Prime Videoの更新は不定期で、「毎週何曜日に更新」となっているものですら不定期だった。 対してdアニメのほうはきっちりやっているので時間差がある。

導入当初ならわかるのだが、既に大荒れコメントからの訂正というレビューが溢れているにもかかわらず放送回が更新されるたびにそんなレビューが追加されるのにはうんざりする。

多分、レビューが参考にならないといっている人はこのような人なのだと思う。 全く読まないか、もくしは読むとしても何かを読み取ろうとするのではなく自分の都合に合致するようにしか受け取らないのだ。 実際、このようなレビューは「他の人も言っている」とレビューしていたりするのだが、その人は訂正も入れているはずなのだが。

私はAmazonの対応よりも、自発的に何かを考えたり受け取ろうとしない愚かな人の多さによっぽど絶望している4


  1. AKBの楽曲があるので、AKBが好きな人なら満足したかもしれない。

  2. コンテンツ的にも削除が相次いで価値は少し下がったが、これは「PrimeはAmazonの特別なサービスを受けられる」から「PrimeはAmazonの他のサービスの体験版がついてくる」に位置づけとしてグレードダウンしたという話だ。

  3. これに関しては意見は様々だろうけれども、削除が目立ち、放送と連動したものも不定期にアップデートされ、みたいと思うような作品はなかなかPrime扱いにならないなど本屋の安売りワゴンのような様相を呈してきているように感じる。

  4. もちろんAmazonのやり方が適切だとも思わないが、それは「Primeの付加価値が低下し、存在価値が微妙になった」というだけのことで、サービスの質の低下についてとやかく言うことでもない。