Home > Latest topics

Latest topics 近況報告

たまに18歳未満の人や心臓の弱い人にはお勧めできない情報が含まれることもあるかもしれない、甘くなくて酸っぱくてしょっぱいチラシの裏。RSSによる簡単な更新情報を利用したりすると、ハッピーになるかも知れませんしそうでないかも知れません。

萌えるふぉくす子さんだば子本制作プロジェクトの動向はもえじら組ブログで。

宣伝。日経LinuxにてLinuxの基礎?を紹介する漫画「シス管系女子」を連載させていただいています。 以下の特設サイトにて、単行本まんがでわかるLinux シス管系女子の試し読みが可能! シス管系女子って何!? - 「シス管系女子」特設サイト

Page 4/243: « 1 2 3 4 5 6 7 8 »

Fox SplitterのLinuxでの挙動の改善と、Mac OS Xで残された課題 - Mar 25, 2012

Fox SplitterをWindows以外で使った時に 実にパネェ感じでストレスフルな挙動を示す件について、とりあえずLinuxではちょっとだけ改善できた気がする。

要点を先にまとめておくと、こういうことだ。

  • Windows上では以前から、ウィンドウの1つが選択されて最前面に来たら、グループ化された他のウィンドウもそれによって「押し上げられ」て最前面に来る、という挙動になっていた。
  • でもFirefoxの仕様上の制限で、LinuxとMac OS Xではそれができていなかった。
  • 今回、Linuxではwmctrlを呼び出すことによってWindows上と同じような挙動を再現できるようになった。
  • Mac OS Xで同じ事ができるのかどうかは分からないままである。
  • JSDeferredはやっぱり素晴らしいです。

以下、背景も含めた詳しい話。

続きを表示する ...

tabFx2Compatible.xul、tabFx2Compatible.css、tabFx2Compatible.xmlを使わないようにした - Feb 09, 2012

ツリー型タブ情報化タブの今日付でのリリース分から、tabFx2Compatibleという自作のライブラリ(?)を使わないようにした。当初はマルチプルタブハンドラでも使ってたけど、ツリー型タブ・情報化タブに先駆けて一足先に使わないようにしていた。今回残りの2つでも利用をやめたことで、TBEやり直し組のアドオンからはこのライブラリが全く姿を消したことになる。作ったのが2008年の2月からだから、丸4年くらいは使ってたのか。

このライブラリは元々、Firefox 3での仕様変更に追従するために仕方なく作った物だった。

Firefox 2ではタブの中に任意の要素(サムネイル描画用のcanvasだったりカウンタ表示用のlabelだったり)をXBLのコンテナ要素を使って動的に追加できていた。しかしFirefox 3になる時、具体的には2007年の12月頃に、高速化のためにそういう冗長性を排除する変更が行われてしまって、JavaScriptで動的にタブの内容を追加するということが原理上不可能になってしまった。

正確には、方法はあった。Firefox本体がタブに適用していたXBLによるバインディングを独自のバインディングで置き換えて、それを使ってタブの内容を変更するというやり方だ。しかし、XBLのバインディングは同時に1個だけしか適用できないという制限がある。複数のアドオンが同じ事をやろうとしたら、結局どれか1つのアドオンしかまともに動かないという事になってしまう。他の人の作る物との互換性という話に限らず、リッチでファットなAll-in-One型のアドオンであったTBEを捨てて各機能ごとに個別のアドオンに開発し直す道を選んでいた僕にとっては、自分の手がける物同士の互換性を維持するためにも、これは致命的な問題だった。

前述のライブラリは、特定のアドオンのために特化したバインディングを適用するのではなく、Firefox 2時代の「ある程度好きなようにタブの内容を増やせる余地がある」、冗長性を持った汎用的なバインディング定義を、Firefox 3向けに復活させるという物だった。

風向きが変わったのは2010年9月の事だった。Firefox 3.7のモックアップで示された視覚的なデザインを実現するために、タブのバインディングに再び冗長性が付与された。メジャーバージョンとしては、この変更はFirefox 4から反映されている。僕はこの仕様変更をうけてtabFx2Compatibleを改修し、Firefox 4以降のタブのバインディングの構造と、Firefox 2以前のタブのバインディングの構造の、両方を併せ持つ状態に変更した。

という経緯を見ると分かるかもだけど、このtabFx2Compatibleというライブラリは本質的に、Firefox 3.0から3.6までの間のバージョンに対応するためには欠かすことができなかった。ツリー型タブ等のアドオンの対応バージョン範囲の下限がこの範囲に重なっている間は、このライブラリは絶対に使う必要があったので、いくらTMPやVimperator等とバインディングの衝突の危険性があったとしても、構成ファイル群から外すことができなかった。

今回、Firefox 10のESR(延長サポート版)がリリースされたことにより正式にFirefox 3.6の死期が確定したので、サポート終了を待たずにFirefox 3.6のサポートを打ち切って、それと同時にtabFx2Compatibleも廃止することにした。レガシーなFirefox 2由来のDOMツリー構造を前提にして書かれたスクリプトやスタイルシート等を、全面的にFirefox 4以降の既定のDOMツリー構造に合わせて変更する作業は、それなりの手間を要したけれども、これでカビの生えた過去から決別できるのなら安い物だと思った。

選択肢の1つとして、tabFx2Compatibleを今後も使い続ける(Firefoxのタブのバインディングの構造が変わったら、その度にtabFx2Compatibleを更新していく)というやり方もあった。今この瞬間にかける労力を最小化する事を選ぶのなら、そういう選択もあり得たと思う。でも、tabFx2Compatibleは元々Firefox 3から3.6までの暗黒期を乗り越えるためだけに用意された物だったのだから、用済みになったのなら、思い切って捨てた方が今後のためになると思った。

こういう切り替えをできる時にやっておかないと、またTBEみたいな事になってしまう恐れがある。TBEでは、タブの移動等といった基本的な機能すらFirefox本体に備わっていなかった頃から開発していたため、TBE自身で独自の「タブを移動する」などのAPIを実装していた。そういう古いオレオレAPIから、Firefox 1.5くらいから新しくFirefox本体に備わったTabMoveとかのDOMイベントベースでのやり方にスイッチする事の手間を惜しんで、「とりあえず今動いてるから」と独自のオレオレAPIを維持することに固執してしまったがために、TBEはFirefox 1.5とともに時代に取り残され死んでしまった。そんな愚はもう繰り返してはいけない。

それにつけても、あの辺(Firefoxのタブまわり)の開発をやってる人達の意向に振り回されっぱなしだった4年間だったなー……と思うと、なんか感慨深い。

ツリー型タブでタブのツリー構造を高速に復元できるようにしたりPDFでも「自動でタブバーを隠す」できるようにしたりした - Dec 14, 2011

Tree Style Tab 0.13.2011121401で、長年の課題だった点に対する改善を入れてみた。現実逃避です。

まず1点、ツリーの復元にすごく時間がかかるという問題。

今まではSSTabRestoringイベントのタイミングでツリー構造を復元してたんだけど、これだとタブがちょっとずつしか復元されないせいでツリーもちょっとずつしか復元されない→ツリー全体が復元されるまで場合によってはものすごく時間がかかる、という問題があった。でもSSTabRestoringイベントが発行される前の時点ではnsISessionStoreのsetTabValue()で保存した情報を取り出せないからどうしようもなくて、ずっと放置してた。

これが最近のバージョンのFirefoxではSSTabRestoringより前でもセッションに保存された情報を取り出せるようになってたので、じゃあってんで、真っ先にツリー構造だけ復元するようにしたという次第。

前のエントリではnsIObserverでメッセージを拾うとか何とか書いたけど、結局その方法はやめた。最終的にどうやったのか、という事を簡単に書いておく。

おさらいとして、Firefoxが備えているセッション復元機能は以下のような流れで処理を行っている。

  1. SSWindowStateBusyイベントが発行される。
  2. 必要な数のタブを開く。タブを使い回す時は、今読み込んでいるタブの内容を破棄する。
  3. セッションの情報に基づいてタブを初期化する(表示・非表示の切り替え、タイトルの設定など)。この時SSTabRestoringイベントが発行される。
  4. セッションの情報に基づいて履歴を復元する。この時SSTabRestoredイベントが発行される。

問題は、1と2の間に割り込んで、2で使い回される事になるタブのツリー構造を一旦リセットしないといけないけど、そのためのAPIが無い(どのタブが使い回される事になるのか、を知る方法が全く無い)っていう事。

  • __SS_tabStillLoadingとか__SS_restoreStateとかを見たら分かるんじゃないか?と思ったけど、これを使っても、「Bar Tab相当の機能」によって待機状態のままになってるタブと、これからセッションが復元されようとしている状態のタブとを見分けられない。
  • プロパティアクセスやDOMノードへの属性値の設定を監視するのはコストが大きそうだし、他のアドオンやFirefoxの機能を壊してしまいそう。
  • タブを使い回す直前にnsISHistoryのPurgeHistory()というメソッドが呼ばれていて、nsISHistoryにはnsISHistoryListenerインターフェースを備えたリスナを登録できるようだったので、これを使えばいけるか!?と思ったけど、nsISHistoryには1個しかリスナを登録できなくてアドオンでリスナを追加するとFirefox自身が追加したリスナが失われてしまって、全体的に動作がぶっ壊れてしまった。
  • nsSessionStoreはJavaScriptコードモジュールではなくXPCOMコンポーネントなので、プロトタイプやシングルトンとして動作してるインスタンスに対してフックを仕掛ける事もできない。

とかなんとかああでもないこうでもないといじり回していて、もう最後の手段という事で、<browser/>stop()を置き換えてフラグを立てたり下ろしたりするようにした。nsSessionStoreは1と2の間で、使い回す予定のタブをプライベートメソッドのrestoreHistoryPrecursor()に渡してそれらの内容を初期化するという事をやってて、その中で必ずstop()を呼んでいたので、stop()が呼ばれた時にJavaScriptのスタックを辿って、restoreHistoryPrecursor()から呼ばれていたら「このタブはこれから使い回されようとしている」というフラグを立てるようにしたrestoreHistoryPrecursor()は他の場所からは絶対に呼ばれないから、これが一番確実だと思う。

そうすると、

  1. SSWindowStateBusyイベントを拾って、「これからツリーが復元されようとしている」ことを検知して、「ツリーが復元されようとしている」フラグを立てる。
  2. restoreHistoryPrecursor()のタイミングで、「これからセッション情報が復元されようとしているタブ」にフラグが立つ。
  3. 復元されるタブの1個目に対してSSTabRestoringイベントが発行される。この時、「ツリーが復元されようとしている」フラグが立っていたら、2でフラグが立てられたタブだけを収集してきてツリー構造を復元する。
  4. 2つ目以降のタブのSSTabRestoringイベントが発行される。以下略。

という具合にして、個々のタブのセッションの復元完了を待たずに一気にツリー構造を復元できるようになるわけです。

この改善は、Firefoxのセッション復元APIを使ってるSession Managerとの併用でもちゃんと活かされる。Tab Mix Plusみたいに独自のオレオレセッション復元機能を持っててそれを使ってる環境は……知らない。多分動かないだろうけど対応する気力無い(そもそも、僕自身Session Managerは使っててもTMPは使ってない)。

次、2点目。タブで開いてる内容がPDFだったりFlashだったりすると「タブバーを自動で隠す」が機能しないという問題。

ポインタの位置に応じて自動的にタブバーを表示したり隠したりという事をやるためのベタなやりかたは、Firefoxのウィンドウ(XULドキュメント)でキャプチャリングフェーズでmousemoveイベントを監視するという方法だ。ポインタがタブバーの近くに来たらタブバーを表示して、コンテンツ領域の上に載ったら(タブバーから離れたら)タブバーを隠す、という感じ。AutoHideというアドオンはそうしてたし、ツリー型タブもそうしてる。

ところが、何度か中野さんが解説されてた気がするけど、Firefoxはプラグイン(FlashとかPDFとか)の描画領域の上で発生したクリックやら何やらのイベントは全部プラグインが握りつぶすようになってる。そのため、普通にmousemoveイベントを監視してても、プラグインの領域にポインタが載ってる間は何もイベントが発生しない。ポインタがタブバーから離れた事はmouseout等で検知できても、コンテンツ領域に載ったという事を検知する事ができない。

(ちなみに、ツリー型タブではタブバーの「近く」にポインタがあるときはタブバーを隠さないで、ちょっと離れたら初めてタブバーを隠す、という風にしている。そうしないと、タブバーの幅を変えるためにスプリッタをドラッグしようとしても、ちょっとポインタがぶれただけですぐタブバーが隠れてしまってストレスが溜まってしょうがない。なので、mousemoveでポインタの座標を監視するという方法に頼らざるを得ないのです。)

同じ理由で、マウスジェスチャ系のアドオンもプラグインがあるとジェスチャがまともに動かないという事が結構あるみたい。そこをどうにかしようとすると、CとかC++とかでコンポーネントを作ってもっとプラットフォーム寄りの所でポインタの位置を拾うしかなくて、「プラグインの上でもジェスチャできる」が売りのMonkey Gesturesは実際そのようにしてたと思う。

ネイティブなコンポーネントを書くというのは嫌っていうかそんな手間かけたくなかったので代わりにどうやったかっていうと、すごく単純な話で、background: rgba(0,0,0,0.01) !important; -moz-appearance: none !important;にした<panel/>をコンテンツ領域の上に重ねて開くようにした。たったそれだけ。そうするとXULの要素の上だから普通にmousemoveイベントが発生して、ポインタの正確な位置を取れるようになった。

透明なポップアップを表示する時には、セオリーというか注意点がいくつかある。

  • background: transparent !important;で完全な透明にしてはだめ。完全に透明な<panel/>は何のイベントも拾ってくれない。なので、rgba(0,0,0,0.01)(ものすごく薄い半透明の黒)のように、何かとにかく色を付けておく必要がある。
  • Linuxでは半透明のpanelは表示できない(Geckoが対応してなくて、ピクセルごとに完全透明か完全不透明かのどっちかしかできない)。なので、background: transparent !important;で完全透明にしつつborderでちょっとだけ線を表示して、<panel/>の中に不透明な部分を作ってやる。
    • ただ、それだとcompiz等ではpanelに影ができてしまってかっこわるい。不透明な部分が矩形になってると影ができて、矩形以外の形だと影ができないっぽい(ロケーションバーのfaviconの所に出るドアハンガーUIに影が表示されないのもこれが理由)ので、<panel/>の左右にだけ枠線を付けるという風にして、領域が矩形にならないようにする。

透明な<panel/>を使う方法にはいくつか弊害があって、今まではそれを気にして採用を避けてた。が、今回のアップデートではそれぞれ「できる所までは頑張ろう、どうしても無理な所はもう知らん」というスタンスで割り切ることにした。

  • ユーザがコンテンツ領域の中をクリックしたつもりで<panel/>がクリックされてしまうと、「クリックしたのに何も起こらない」という状況が発生してしまう。
    • →タブの内容がプラグインで表示されてるかどうかを見て、必要な時だけ透明な<panel/>を使うようにした。タブバーが隠れて<panel/>が閉じられた後でなら普通にクリックできるので、タブバーが隠れる前にコンテンツ領域をクリックするようなせっかちな人の事はもう諦める事にした。
  • 透明な<panel/>以外の部分(ツールバーボタンなど)をクリックすると、環境によっては、透明な<panel/>が閉じられるだけで終わってしまう。
    • popupBoxObject.setConsumeRollupEvent(Ci.nsIPopupBoxObject.ROLLUP_NO_CONSUME)ある程度は抑制できるっぽい(Ubuntu 10.04LTSのcompizだと、Firefoxのウィンドウの中に対してはclick-throughが通用するようになったが、他のアプリケーションのウィンドウをいきなりクリックした時は相変わらずだった)。どうしても駄目な時については、もう、諦める。

なんで方針を変えた(安全に完璧に提供できない弊害の多い方法は使いたくない→弊害があっても使う)かというと、「同じ要望がもう数えるのも嫌になるくらいしょっちゅう来ててウンザリしたから」っていうのが最大の理由だ。

いや、つまり「PDFとか表示してるとタブバーが隠れてくれない」問題は、割と誰でもぶち当たってしまう問題なわけですよ。それに対して、実際に調べたわけではないけど、多分上に挙げたような「弊害」が実際に致命的な問題になるような人は多分そんなに多くないだろうと思うわけですよ。どっちの人を大事にしたらいいかっていう事で天秤にかけて、前者を救う事にした。という話なのです。

そういう意味では、TMPの独自のセッション復元機能を使ってる人を見捨てるってどうなんっていう言い方もあるだろうけど、あんなもん(TMP独自のセッション復元機能)ぶっちゃけ捨てていいですよ。Firefox本体のセッション復元機能に勝ってる部分、ありますか? ないですよね? いやよく調べないまま書いてるんだけどさ。

Firefox Hacks Rebooted 4章正誤情報速報 - Nov 20, 2011

Firefox Hacks Rebootedの正誤表を早いとこ作らないといけないという事は認識しているのですが、他の事に忙殺されていて手を着けられていません。なので、自分の担当章で現在把握しているミス、出版後に状況が変化した点などについて書いておきます。(ここに書いた内用は、いずれ本書のサポートサイトにもまとめる予定です。このエントリは「速報版」ということで。速報と言うには遅すぎますが……)

Bootstrapped Extensionsでのchrome.manifestについて(Hack#33 、217ページ)

本書での解説のうち、chrome.manifestの読み込みの方法の記述が事実と異なっています。

Components.manager.addBootstrappedManifestLocation()およびComponents.manager.removeBootstrappedManifestLocation()には、 chrome.manifestのファイルの位置ではなく、XPIファイルもしくはchrome.manifestがあるフォルダの位置を渡します。別のファイル名・別の位置のマニフェストファイルを読み込ませたい場合は、chrome.manifestの中からmanifestディレクティブで間接的に読み込ませる必要があります。

なお、Firefox 8および9ではBootstrapped Extensionsに含めたchrome.manifestは自動的には読み込まれませんが、Firefox 10からは自動的に読み込まれるようになります(Bug 675371)。

e10s(プロセス分離)について(Hack#34~38、219ページ~249ページ)

各地で既報の通り、デスクトップ版Firefoxのe10s有効化は当面行われない事になりました。これらの節で解説しているMessage Managerの仕組み自体はまだ残されるものと思われますが、個人的な予想として僕はMessage Managerの仕組み自体も将来的に削除されてしまう可能性があるとも考えています。ですので、何らかの事情でどうしても使わないといけないという事でない限りは、Message Managerの仕組みは使用しない事を、僕個人としてはお勧めします

かなりのページ数を割いたにも関わらずこういう事になってしまって、本当に残念です。既に本書の内容を参考にe10s対応のための準備を始めていた方もいらっしゃる模様で、Firefox 3 Hacksの時のFUEL解説と同じように、結果的に皆さんを振り回してしまう事になってしまい誠に申し訳ありません。

プログレスリスナの実装について(Hack#33 、237ページ~238ページ)

サンプルコード中でnsIWeakReferenceという記述がありますが、これはnsISupportsWeakReferenceの誤りです。

ワーカースクリプトでのdata: URIの利用について(Hack #42、271ページ)

data: URIは利用できないと書いていますが、Firefox 10からはdata: URIも利用できるようになります(Bug 699857)。

ワーカースクリプト内でのXPConnectの利用について(Hack #42、276ページ)

本節ではChromeWorkerの名前空間で、XPConnectへのアクセスのためにXPCOMというオブジェクトを利用できると書いていますが、Firefox 8正式版ではこの機能は廃止されました(Bug 649537)。ワーカーの名前空間からは、XPConnectは一切利用できません。

ただ、本節で述べている通り、元々ワーカーの名前空間からXPConnect経由で利用できる機能はほとんど無かったという事と、js-ctypesは引き続き利用できる(Nightlyで実際に確認しましたので、これは間違いないです)という事から、実質的にはほとんど影響の無い変更だったと言えます。

再起動のいらないアドオンのコンテストが11月8日頃〆切で行われているそうですね - Nov 01, 2011

Firefoxアドオンコンテストの要項を意訳してみた。 - おんがえしの日記で報じられていますが、「再起動のいらないアドオン」というテーマでアドオンのコンテストが開かれているそうです。

再起動のいらないアドオンというとAdd-on SDKを使って開発すればそういう風になる訳ですが、何度か勉強会等で話している通り、再起動のいらないアドオンを作るだけならSDKなしでも作る事は可能です。そういう物も応募できるのか? という質問がやはり告知のページにも寄せられていて、回答としては、「SDKなしでもいいよ」と書いてありました。なので、老害のくせに性懲りもなく応募してみる事にしました。

まずFox Splitter

URL
https://addons.mozilla.org/firefox/addon/fox-splitter/
Name
Fox Splitter
Description

Do you want to browse multiple webpages (ex. "English version" and "translated version") side by side? This can do it.

This provides ability to "split" a Firefox window to multiple ones, and manages them (grouped windows) like a large window with multiple panes. To "split" the window, "Split" button in the navigation toolbar is available. Otherwise, you just have to drag a tab to near the inner edge of the window itself, and stay there. Then a drop position marker will appear like the screenshot: https://static-cdn.addons.mozilla.net/img/uploads/previews/full/59/59710.png?modified=1309171529 Not only two panes, but also three, four, or more "panes" are available. Of course, when you resize a member window, others also fit to it like panes in a large window.

This is developed without Add-on SDK but based on my tiny framework named "Restartless", including customizable toolbar items, configuration dialogs, l10n, Firefox 3.6 support, and so on. https://github.com/piroor/restartless

あと、Back to Owner Tab

URL
https://addons.mozilla.org/firefox/addon/back-to-owner-tab/
Name
Back to Owner Tab
Description

Have you met such a stressful situation?: You finished to read a webpage and want to back to the previous page, but you can't click the "back" button because it is disabled - yes, you were in a new tab opened from the previous page, so you have to close the current tab instead of clicking "back" button.

This provides ability to go back/forward across tabs/windows. Even if the current page is in the first (or last) entry in the history, the "back" (or "forward") button is still enabled. If you click the button, then the owner tab (or the "next" tab - it had focus before the "owner") gets focus.

This is developed without Add-on SDK but based on my tiny framework named "Restartless", including customizable toolbar items, configuration dialogs, l10n, Firefox 3.6 support, and so on. https://github.com/piroor/restartless

最後にさらに宣伝しておくと、先日発売されたオライリーのFirefox Hacks Rebootedには、GomitaさんによるAdd-on SDKを使ったアドオン開発のチュートリアルと、Add-on SDKを使わない再起動不要なアドオン開発での色々なテクニック・注意点のまとめの両方が収録されています。再起動不要なアドオンには興味があるけど、まとまった情報が無くて二の足を踏んでる……という方がもしいらっしゃいましたら、こちらの本を片手に挑戦してみるといいかもしれませんね。

Firefox Hacks Rebooted、オライリーから出ました - Oct 27, 2011

既にご存じの方もいらっしゃるかとは思いますが、オライリーから「Firefox Hacks Rebooted」という本が出ました3年前に出た「Firefox 3 Hacks」の続き……でもないのですが、似たようなコンセプトで「今」の話をまとめた本です。

本1冊を通して1つのストーリーに基づいて何かを体系立てて解説する、という本ではなくて、各著者が自分の得意分野で好きなように書きたい事を書きまくった本、というのが実情を正しく言い表している気がします(元々、オライリーの「○○ Hacks」というタイトルは「なんでもあり」のブランドなんだそうで……その言葉に甘えてしまいました)。

以下、各章の対象読者層と思われる層、内容の簡単な紹介と、定量的に傾向を把握するための手がかりとしてページ数と全体に対する割合を表にしてみました。これを見ると一発で分かりますが、僕(4章と6章の一部を担当)の暴走が著しいですね。やばい。

主な対象読者層 内容 ページ数 全体の中でのパーセンテージ
1章 エンドユーザ Firefoxの新機能紹介など基本的な事。Firefox 3.6とFirefox 4以降との間で何が変わったのかのまとめ。 54 11%
2章 開発者寄りのユーザ VimperatorとKeySnailの解説。と、Twitter用アドオンの解説。ブラウザとしてのFirefoxをガンガン使いこなしていく人向け。 42 9%
3章 アドオン開発者 Add-on SDKを使ったアドオン開発のチュートリアル。アドオンの開発をこれから始めたいという人向け。 68 14%
4章 アドオン開発経験者 Bootstrapped Extensions、ChromeWorker、e10sなど、Add-on SDKよりも下のレイヤの技術の解説。今既にアドオンを開発してるという人や、Add-on SDKではできない・標準ライブラリでカバーされてない範囲の事に手を出そうと思ってる人向け。 156 33%
5章 Webデベロッパー Firefoxで利用できるHTML5関連技術やECMAScriptの紹介。Webデベロッパー(主にフロントエンド)向け。 98 21%
6章 アドオン開発経験者、Webデベロッパー ハードウェア寄りの話と、その他のこぼれ話。アドオンやWebアプリの開発で、ネイティブアプリ並の事をやりたい人向けの話が多め。かも。 56 12%

自分の担当箇所だけ細かく見てみると、ページ数と全体に対する割合はこんな感じです。

  • Bootstrapped Extensions(再起動のいらないアドオン)の話:54ページ、11%
  • 非同期処理の紹介:72ページ、15%
    • そのうち、JSDeferredの紹介:43ページ、9%
  • js-ctypes(6章):27ページ、6%

調子に乗って脳汁ドバドバ出して書きまくる→ページ数が増える→値段上がる→損益分岐点も上がる という危険なコンボが発動してしまったためかお値段高めとなっておりますが、自分の担当箇所も他の方の担当箇所もひっくるめて、腰を据えて読むに値する情報ばかりなんじゃないかなーと思っております。Webで難なく読める文章の長さと、(紙でも電子でも)書籍の形になってた方が読みやすい文章の長さって、やっぱり違うと思いますしね。

本書のサポートサイトも公開されており、正誤表や本文中の各コードリストのダウンロード、本文の一部を切り出したサンプルPDFの無償公開などがあります。正誤表等はこれから更新されていくと思いますので、本書をお読みになられる際はこちらのサイトも併せてご参照いただければ幸いです。

以下は、思い出話です。

本書の企画がスタートしたのは、Firefox 4の正式版が出る前の2010年5月頃だったと思います(今メールボックスの一番古いメールの日付を見て確認した)。当時はまだ内部バージョンがFirefox 3.7とか言われていた頃で、Aero Glassが標準で入るのか?とか、そんな事を言ってた時期でした(という事も今Wikipediaを見て確認した)。

それからしばらく、どんな内容にするのがいいか? どんな人に執筆を依頼しようか?(今著者の一覧に名前が載ってる方の中には、最初の時点で名前が挙がってた著者の側から「是非この人にも書いてもらいたい!」と引っ張り込んだ人もいるのです) という事を話し合っていて、執筆者が確定したのが8月。そこからぼちぼち書き始めて、なんやかやで1年経ってしまいました(普通はここまで難産にはならないみたいです)。その間にFirefoxのバージョン番号もどんどん上がっていって、もうすぐFirefox 8ですよ奥さん! 時間が過ぎるのは本当に早いものですね。

最初の頃は、自分は「Firefox 3 Hacksで書いた内容をFriefox 4時点での情報に基づいてリライトするか?」程度の事を考えていました。でも、それじゃあ書いてる自分がつまらないし、それこそすぐに陳腐化してしまいます。それでうんうん唸りながら調べていくうちに、Firefox 4以降の話で新しい基盤の技術になりそうなトピックがいくつかあるという事が分かってきたので、それじゃあってんで、そこをターゲットにして書いていく事にしました。実は、自分の担当箇所は半年くらい前にほぼ完成してたんですよね。そこから本書の発売までの間は、(他の事に時間を使ってたからというのもありますが、)細かい記述のアップデート程度しかやってません。高速リリースになってからガンガン方針が変わったり実装が変わったりしてて、本書に書いた「テクニック」の中にも、既に「もうこんな回りくどい事しなくてもいいんだけどなぁ」な感じになってしまった話題がいくつかあるにはあるのですが(校正の詰めの詰めに入った段階でまたどどっと変更が入ってきて、どーしても間に合わなかったんです……)、全体としてはちゃんと今でも、そしてこれからも通用する話になってると思います。あの時の自分の目の付け所は、そんなには間違ってなかった、はず。

紆余曲折があった末にようやく世に出る事ができた本書ですが、アドオン開発者の方の手助けとなり、また、アドオン開発に手を出してみようと考えている方の手引きとなれば、幸いです。

他の著者の方々による本書の紹介のエントリ:

Back to Owner Tab(親のタブに戻る)を「進む」に対応させた - Aug 30, 2011

親のタブに戻るで使ってる再起動不要なアドオンのテンプレートそのものに「無効化した状態でアップデートしたら勝手に有効になってしまう」という重大な不具合があったので、その更新も兼ねて、「進む」方向への対応を加えて肉リリースした(太平洋標準時)。

前のバージョンでは単純にタブの.ownerを見て戻る先を判断してたんだけど、これはタブのフォーカスが切り替わるとクリアされてしまうので、1回親のタブに戻ったらそれっきりだった。また、.ownerがクリアされてしまっては、「進む」がクリックされた時にどこに「進」めばいいか分からないし、仮に分かったとしても現在のタブから複数の子タブが開かれていた場合はどこに「進」むのが妥当かという判断がつかない。ということで、「進む」への対応はしてなかった。でも実際使ってたらうっかり「戻」ってしまった後にまた「進」みたくなるという場面が結構あったので、いずれは何とかしたいなーとは思ってた。

で、肉リリース目指してせっかくだから片付けとこうと思って手を付け始めたら、これが結構大がかりな事になってしまって、結局、タブ毎に固有のIDがあって、各タブが自分の親のタブの情報を常に持っていて、ついでに自分が最後にフォーカスされた時刻も持っている、というファットな実装になってしまった(ツリー型タブの初期のバージョンと同じくらいの情報を持ってることになる)。

それでどうなったかというと、前までは1回しか「親のタブに戻る」できなかったのが、何階層でも祖先のタブに「戻」って、その後また元見ていたタブまで「進」む、という事ができるようになった。タブの垣根を越えて透過的に「戻る」「進む」できるというのはかなり変な気分だ。横置きの普通のタブバーでやると、自分が今どのタブを見てるかわかんなくなるんじゃないだろうか。そういうわけで、これはツリー型タブとの併用をお薦めしておきたい(ツリー型タブとの併用時ならツリー構造として既に構築済みの親子関係をそのまま「戻る」「進む」に使えるというメリットもあるのです)。

マルチプルタブハンドラで、タブの選択で一部のタブがスキップされないようになった - Aug 30, 2011

マルチプルタブハンドラはタブの上でドラッグ操作をやると複数のタブを選択できるという物で、mouseoverとまmouseoutとかのイベントを拾ってそういう挙動を実現してるんだけど、mouseover/mouseoutのイベントが発火されない事があるせいで、タブを選択しようとして一部のタブだけ選択されなくてイラッと来る事が時々あった。具体的に言うと、例えばA, B, C, Dの4個のタブがあったとして、AからCまでの3個を選択したくてAの上でドラッグ開始してCの上でマウスのボタンを放した時に、AとCは選択されるのにBが選択されないという感じ。

期待されているイベントが発火されないのはFirefox自体のバグみたいなんだけど、こんなのもうどうしようもないじゃんと思って放置してた。そしたらtitoさん(Komodo EditやSeamonkey用のアドオンを作られている方で、僕のアドオンのいくつかにスペイン語ロケールを提供してくれてる)が「こうすればいいんじゃない?」という提案をして下さったので、プルリクエストで貰ったパッチを参考にもう少し改良した上で実装してみた。基本的な理屈としては、あるタブを選択する時に「直前に選択されたタブ」を保持しておいて、新しく選択されたタブと直前に選択されたタブの間にタブがあればそれらも選択されたものと見なす、というもの。この「直前」の判定基準にはtitoさんのパッチで提案されていた300ミリ秒という数値をそのまま使わせて貰った。

それで実際使ってみたら快適すぎワロタ。今までどれだけこのバグがストレスを産み出していたのか…… タイミングがちょうどよかったから肉リリースしておきました。自動アップデートで皆さんもこの快適さを味わうといいです。

あと、日本語環境向けの細かい変更で、タブを選択した時のメニューのラベルが「Close All」の直訳で「すべて閉じる」とかになってたのを「閉じる」のようにまず動詞が先に来るように直した。こうしておかないと、メニューに項目がずらっと並んだ時にぱっと見で判別できなくて困るという事が多かったので。

Fox Splitterを元の設計に戻して欲しい (Why Fox Splitter lost its functionalities in old versions: multiple panes in a window, not multiple windows?) - Aug 25, 2011

Q

Why did you remove the awesome functionalities from Fox Splitter 0.6 and replaced it with Fox Splitter 2? Fox splitter is now just a way to glue multiple instances of Firefox together.

I would like to ask you to remake the functionality of Fox Splitter 0.6.2009110501, perhaps as it as a function that can be enabled or disabled? Or perhaps just make the 0.6.2009110501 version workable on newer Firefox versions?

どうしてFox Splitter 0.6の素晴らしい機能(※訳注:1つのウィンドウの中を複数のペインに分割する機能)を削除してFox Splitter 2で置き換えたのですか? 今や、Fox Splitterは単に複数のFirefoxのインスタンスをくっつけて一緒に操作するだけの物になってしまいました……

Fox Splitter 0.6.2009110501の機能を復活させて、オプションで有効無効を切り替えられるようにならないでしょうか? それか、単にバージョン0.6.2009110501を新しいFirefoxの上で動作するようにできないでしょうか?

A

I recommend you to try Tile Tabs or Tile View, if you want to split a window to multiple panes and don't want toolbar/tabbar for each pane.

Sorry, Fox Splitter never introduce "multiple panes in a window" feature in future releases. There are some reasons.

After I initially released the old Fox Splitter, I realized that each "pane" should have navigation toolbar for usability. So I actuary did it. However, much codes was required, it had too less maintainability, and it was strongly depended on codes of the specific version of Firefox. So I couldn't update the old Fox Splitter for 1.5 years.

During that time, similar new addons "Tile Tabs" and "Tile View" debuted. I hope that they can replace my old Fox Splitter. However, after I tried them, I couldn't become familiar with their concept. I thought that their "tiled view in a tabbrowser" is hard-to-understand.

Moreover, both "Tile Tabs" and "Tile View" didn't provide navigation toolbar for each pane. I realized that it was a unique feature of my old Fox Splitter and no other addon inherited the concept. I thought that I have to implement such an extension by myself if I want to use it -- no one does it for me except myself.

Yes, I decided to update Fox Splitter. And, I decided to drop functionality to split a browser window to multiple panes, because it requires huge codes and it is very hard to maintain for current rapid-released Firefoxes. I don't want to abandon the new Fox Splitter for a long time anymore. High maintainability (and compatibility) code is strongly required for me. The old Fox Splitter didn't have them and I cannot cover them by my crazy hacking time - now I have less time to do it.

もしあなたが分割されたそれぞれの領域のためのツールバーやタブバーを必要としないのであれば、Tile TabsTile Viewを試す事をお薦めします。

申し訳ないのですが、Fox Splitterが「1つのウィンドウの中を複数の領域に分割する機能」を将来のバージョンで実装する可能性はありません。それにはいくつかの理由があります。

私は、Fox Splitterの最初のバージョンを公開した後で、実用性のためには分割後の各領域がそれぞれ専用のツールバーを持っている方が望ましいという事を実感しました。それで実際にそのような機能を実装しました。しかしそのためには非常に多くのコードを書かなければならず、コードの量が多いという事はメンテナンス性も低かったですし、さらに言うと、それらのコードは特定のバージョンのFirefoxに強く依存した物でした。そのため、私は旧Fox Splitterを更新し続ける事ができず、1.5年もの間完全に放置してしまっていました。

そうこうしている間に、Fox Splitterに似た新しいアドオンの「Tile Tabs」と「Tile View」が公開されました。私は、これらのアドオンが私のFox Splitterの代わりになってくれればいいと期待していました。しかしながら、実際にそれらを試してみると、私にはどうしてもそれらの設計コンセプトに慣れ親しむ事ができませんでした。それらがやっている「1つのタブブラウザの中でタイル表示を行う」というのは、直感的な理解が難しいアプローチなのではないかと、私には思えました。

それに加え、「Tile Tabs」と「Tile View」の両者とも、それぞれの分割された領域のためのナビゲーションツールバーを提供していませんでした。これに至って私は、それが旧Fox Splitterに特有の機能で、そのコンセプトを継承した他のアドオンはまだ登場していないのだという事を理解しました。そのような物を使いたいのであれば、自分自身で実装するしかないーー自分以外の誰もそういう事をやってはくれないのだ、と、私は思いました。

それで、私はFox Splitterを更新する事を決意しました。また、それと同時に、実現するために非常に多くのコードが必要になる上に、現在の高速リリース体制になったFirefox向けにそれをメンテナンスし続ける事は非常に難しいということで、1つのウィンドウの中を分割する機能を廃止する事も決めました。私はもうこれ以上、Fox Splitterを更新できないまま長い期間放置してしまうような事になってしまうのを望んでいません。高いメンテナンス性(そして互換性)を持つコードこそが、私の求めていた物でした。旧Fox Splitterにはそういう視点が欠けており、そういった問題を絶えず修正し続けるために狂ったように多くの時間を注ぐ事は、今の自分には不可能だとも思っています。

Firefoxアドオンの開発を通じて考えるようになったインタラクションデザイン - Jun 30, 2011

あかつかだいすけさんのご紹介で、6月27日に慶応大学湘南藤沢キャンパスでインタラクションデザインについての講義を1時間ほどやらせていただきました。その際の発表資料はいつもの通り「高橋メソッド in XUL Returns」で作ったのですが、Remote XULがデフォルトで禁止されるようになったFirefox 4以降だとこれを見るためには色々と面倒が多いので、代わりに講義の内容を思い出しながら資料を引用しながらエントリにまとめてみたいと思います。

事前に伺っていたオーダーは、これまでのアドオン開発の中でUIという点についてどういうデザインポリシーを持って開発してきたのかを、また、コンセプトを実装する際の経験から得られた知見を語るというものでした。今までにもこの場やTwitter等で断片的に語ってきている事ではありますが、改めて整理するいい機会になったと思います。

自己紹介

まず簡単に自分の事をお話ししておきましょう。

僕は大阪出身の28歳で、Firefoxのアドオンとの関わりは「Firefox」というプロダクトが世に出るより前からなので、もうそろそろ10年になろうとしています。アドオンをやり始めた頃は大学1年とか2年とかの頃だったと思いますので、講義を聴いていただいた皆さんくらいの年の頃からということになります。卒業制作(僕のいた学科では卒論ではなく卒業制作、しかも選択制だったのです……)もMozillaの拡張機能で「2次元的にWeb閲覧の履歴を表現する履歴表示UI・兼・Webブラウズ用UI」という物だったので、余計に感慨深い物があります。

そういう僕ではありますが、今はクリアコードという受託開発の会社でプログラマとして勤務しており、最近はRubyでWebサービスを作るといった案件に関わっています。仕事の上でインタラクションデザインの事を考える事は実際の所ほとんどなくて、そういう事を実践する機会趣味のアドオン開発の場面くらいしか無いというのが実情です。(きちんとインタラクションデザインの事について学んでいる人に比べると、おそらく物凄く初歩的な事しか理解していない、本来であれば人前でインタラクションデザインについて一席打っていいような立場ではないとは思っています。)

自分はこの何年かで数だけはやたら多くのアドオンを開発してきましたが、インタラクションデザインという観点から語りやすそうな物として、以下の4つを特に取り上げて語ってみたいと思います。

  • ツリー型タブ:タブバーをウィンドウの上ではなく左に移動して、タブを縦に並べて表示し、タブの親子お関係をインデント幅で表現する。
  • マルチプルタブハンドラ:複数のタブをドラッグで選択して、まとめて閉じたりリロードしたりと言った操作を可能にする。
  • Fox Splitter:Firefoxのウィンドウを複数の表示領域に分割し、複数のページを平行して閲覧できるようにする。
  • セカンドサーチ:FirefoxのWeb検索バーにおいて、文字を入力した後で実際に使う検索エンジンを選べるようにする。

自分がUIをデザインする時に気をつけている事

5W1Hで目的をはっきりさせる?

ニュース記事を書く時の5W1Hという原則をご存じでしょうか。

  • 誰が(Who)
  • いつ(When)
  • どこで(Where)
  • 何故、何のために(Why)
  • 何を(What)
  • どのようにしたのか(How)

これらをきちんと抑えた文章にする事で、一体何の記事なのか、どういう事が起こったのか、という事を読者に過不足無く伝えられるという原則が5W1Hです。

僕は、UIのデザインにおいてもこれらの5W1Hが重要だと思っています。

  • 誰が(Who)
  • どういう利用局面で(When、Where)
  • どういう目的で(Why)
  • 何を(What)
  • どのように操作するのか(How)

これらを満たす事のできるUIを考える、というのが出発点としては分かりやすいのではないか。闇雲に「何か新しいUIを」と考えるよりも、これらを意識した方がゴールを設定しやすいのではないか。という事です。

何事でも目的は大事です。特にソフトウェア開発では、無目的に「単に技術的に可能なので作ってみました」という風に生み出したプロダクトがあっても、自分で使わないし誰も使わないために、そのまま死んだプロジェクトになってしまう恐れがあります。

ただ、それとは逆の場合もあると僕は思っています。「単に技術的に可能なので作ってみました」という物を、試しに自分で使ってみたら案外使い勝手が良かった。常用するためにもっと改良したくなった。というケースが僕には実際にありました。ツリー型タブは、元を正せばそのようにして生まれたアドオンです。

ツリー型タブの誕生の経緯

かつて僕はタブブラウザ拡張(Tabbrowser Extensions、TBE)という、Mozilla SuiteやFirefoxの貧弱なタブブラウズ機能をなんとなくいい感じにパワーアップするというようなオールインワン型のアドオンを開発していました。

その頃既に僕は、10とか20とかの多数のタブを同時に開いてWebを閲覧するという使い方をしていました。そういう使い方だと、通常の横一列のタブバーだと、今見ているタブが画面外に吹っ飛んでしまったり、さっきまで見ていたタブがどこに行ってしまったのか分からなくなったり、という具合に色々困った事が起こります。それで僕は2つの機能をTBEに持たせていました。

  • タブバーを多段表示して、1度に多くのタブを見えるようにする。 (タブバーを多段表示した様子)
  • タブを色分け表示して、どのタブからどのタブを開いたのかという親子関係を色で示す。 (タブを色分け表示した様子)

「多段タブ」は、僕がWindows 95を使い始めた頃から時々見かけていたインターフェースでした。Windowsのコントロールパネルで多数の設定項目を持つ項目を開いた場合に、そのダイアログが多段タブになっている場合があったからです。タブが多ければ2段や3段に分けて表示すればいい、というのは日常的に使うWindows自体の一般的なUIを見ていれば自然と思い浮かぶ発想でしょう。

タブの色分け表示は、元々は何か他のブラウザがそういう機能を持っていたのを真似て実装したような記憶があります。親となるタブと子タブとを同じ色で表示しておけば、タブの親子関係が一目で分かるようになります。IE7でもリンクからタブを開くとそれと同じようにタブが色分け表示されるようになっていましたが、当時としては、これもまたそう珍しくない機能だったのでしょう。

そこにツリー表示機能を加えるきっかけになったのは、malaさんが自身のブログで紹介されていたiRiderというIEコンポーネントブラウザでした。

livedoor Readerの開発者として知られるmalaさんは昔からJavaScriptで変態的な、もとい、他の人が思い付いたり実践したりしていなかったような先進的な試みを色々とやっている方なのですが、そのmalaさんが2005年に2005年もパクられてこなかったもの私的まとめベスト3というエントリを書かれていた際に、iRiderというブラウザの名前を挙げておられました。今では配布元のドメインが失効していて百式のエントリにあるスクリーンショットくらいしか様子を窺える物が残っていないのですが、あのmalaさんが(「あの」って付けるくらいに、僕はmalaさんの着眼点はいつも鋭いと考えているのです)名前を挙げているくらいなのだからさぞかし凄い物に違いない!と思ったので、興味本位に加えて腕試しにという思いもあって早速TBEに「タブの親子関係を色分けだけでなくツリー表示というシルエットの変化で示す」という機能、あと、リンク先のエントリでも触れられている「撫でるインターフェース」も併せて実装しました(実はこれが現在のマルチプルタブハンドラの原型だったりもします)。

iRiderのツリー表示というのは、実を言えば、「タブのツリー表示」ではありませんでした。ウィンドウの左に表示されているのはあくまで2次元的に表現されたWebページの閲覧履歴であって、それらの履歴項目をドラッグしたりクリックしたりするとウィンドウの右側でページを見る事ができる、というのがiRiderの挙動です。ただ、当時既にTBEが持っていた「全てのリンクを新しいタブで開く機能」「リンクから開かれたタブを現在のタブの子タブとして扱う機能」にいくつかの機能を加えさえすれば、(メモリの消費量等の観点ではオーバーヘッドはあるものの)表面的にはiRiderと同じような挙動を示すようになるだろうという見通しは立っていました。

ちなみに、タブに相当する物をツリーで表示するブラウザというのは当時既にいくつか存在していたようですが、僕はそれらの事を意識していませんでした。というか、ツリー? 一体何がおいしいの? みたいな認識でした。そういうわけなので、この時はタブをツリー表示する拡張機能を作ったというよりも、iRiderの挙動をFirefoxで(無理矢理)再現するというのが、やった事の本質を正しく言い表しています。

そういう事でとりあえず技術的には可能だったから実装してみるだけしてみたのですが、タブを履歴の代わりに使うというのは当時の自分にはあまりに違和感が大きすぎましたし、iRiderの「履歴」と違ってMozillaのタブは開いていればその間ずっとメモリを消費する物であるという背景もあって、自分はこの時実装した機能のうち「タブをツリー表示する機能」だけを、せっかく実装したのだから……と、ずっと使い続けていました。

そしたら、これが案外便利だったんですね。

という事で自分自身がすっかりツリー機能に依存するようになってしまいました。その後メンテナンスしきれなくなったために僕はTBEの開発を中止しましたが、まずは「なでるインターフェース」の再現のために書いたコードを応用して、その機能だけを抽出して「タブを選択してから操作する」というコンセプトで再設計したマルチプルタブハンドラを公開し、さらに続いて、タブのツリー表示機能だけを抽出したアドオンをツリー型タブとして公開して、TBEの頃と同じような使い勝手を保ち続けて今に至っています。

自分が「良い」と思えるUIのデザインポリシーを逆算する

タブのツリー表示のどの点が便利だと感じたのか、自分自身でもそれと意識する事はなかったのですが、ツリー型タブをMozilla主催のアドオンコンテストに出品するにあたってアピール文を書こうとして、改めて「自分がツリー表示されたタブを使いやすいと感じた理由」を言語化してみる事にしました。

その時自分で分析して思いついた「使ってみて分かったツリー表示のいい所」は、以下のようなものでした。

  • 一覧性が高い。(多数のタブを開いていても、縦に重ねた表示形態であればまだ全体を見通せる。)
  • ページを閲覧してきた履歴がそのまま可視化される。(どのタブからどのタブを開いたのか、どのページからどのページへ遷移したのか、という事がツリーとして視覚的に、2次元的に表現される。)
  • タブが自分の存在を主張してくる。(ブックマークフォルダの奥にしまい込んだ時のように、存在を忘れてしまわないですむ。未消化のタスクがタブとして溜まっていくと、タブバーをだんだん圧迫してきて、「片付けなきゃ」という意識を僕自身に喚起させる。)

これらをもっと突き詰めて一言にまとめると、「ツリー表示であればうろ覚えでも使える」からこそ自分は利便性を感じたからなのではないか。それが自分の辿り着いた結論でした。

うろ覚えで使える、とはどういう事か。もう少し具体的に考えてみましょう。

  1. ボケーッとしてても使える。
    • どこに何があったんだっけ、という事を憶えてなくてもUIを見れば必要な情報がそこにある。
    • 且つ、それらがうるさく主張しすぎてもいないので、多すぎる情報を前にして迷う事がない。
  2. 考えなくても使える。さあこれからこのタスクをこなそう!といちいち気張らなくても使える。
  3. 初見でも使える。使い方を知らない状態で初めて使う時でも、戸惑わないで済む。
  4. 忘れても使える。使い方を忘れてしまって、初めて使う時の感覚に戻ってしまっても、初見と同じようにすぐ慣れる事ができる。
  5. 既存の物に似ている。それ自体の使い方を特別に覚えなくても、他の物からの類推で違和感なく使える。

1は、表示される情報が適切な量になっているという事だと言えると思います。2から5は、学習コストが低いという事です。どうやら僕は、これらの点を満たしている時に「良いUI」と感じているみたいです。

適切な情報量とは

この点はSFCでの講義では話せていなかった点ですが、このまとめでは書いておきます。

情報が適切に整理されている、という事は非常に重要です。例えばある家具屋さんの折り込みチラシを見てみましょう。 (チラシの画像。様々な商品の情報が所狭しと押し込まれている。) この種のチラシは「新春初売りセール開催中ですよ!」という事を顧客に告知して集客する事を第1の目的に、そして売り込みたい商品にどういう物があるのかをなるべく多く知らせる事を第2の目的にしていると考えられます。情報を見やすく整理するという事はあまり重視されていないので、余白を設けるよりも、少しでも多く情報を詰め込む工夫が為されています。顧客はこのチラシの中から目を皿のようにして安い商品を探す事になります。セールのチラシの場合は顧客には「そこにどんな情報があるのかをじっくり読み取る努力をするモチベーション」がありますから、多少の苦難は乗り越えられます。

しかしブラウザのUIは、使い手の側にそれほど強いモチベーションはありません。「さっきまで見ていたタブ」を見つけるためにいちいちこのようなゴチャゴチャした絵面の中を一生懸命探すのは、ただのストレスにしかならないでしょう。常用するUIがこんな感じではとても使えません。

視覚的な情報の量を調整するテクニックはいくつかあります。DTPのセオリーやWeb制作のセオリーなどを読んでもらうといいと思いますが、今自分でもぱっと思いつく物としては以下の4項目があります。

  1. 適切な余白を設ける。要素と要素を詰め詰めに配置しすぎない。(詰め詰めに配置すると、誤操作の元にもなり得る。)
  2. 同じ種類の要素は近くにまとめたり、同じ位置に揃えたりして、グループとして認識できるようにする。
  3. 色を整理する。バラバラの色を混在させないで、同じような物は同じような色でまとめておく。そうする事で、特別な場合にだけ色を変えるという事が「特別」として活きてくる。
  4. 色ではなくシルエットで判別させる。モノクロディスプレイだったり色盲だったりといった色の違いが分からない状況でも、シルエットの違いなら認識できる。また、一般的に色の違いよりも形の違いの方が人は認識しやすい(とどこかで聞いた気がする)。

ツリー型タブによる縦型タブバーの場合、2から4が特に顕著だと僕は考えています。

(ツリー型タブのスクリーンショット) スクリーンショットを見ると分かりますが、縦にUI要素が揃う事で、左にアイコン(とインデント)、真ん中にタイトル、右に「タブを閉じる」ボタンが集まっています。 (ツリー型タブと情報化タブの併用時のスクリーンショット) ここにサムネイルというUI要素が加わっても、縦に同じような位置に同じような物が並んでいるので、これはまとめて意識の外に置いておきやすいはずだ、と僕は思っています。実際、自分はこのようなタブバーの左の方を見ている時は右側を無視していますし、右側を見ている時は左側を無視している気がします。

逆に、横置きのタブバーでは、「アイコン、タイトル、クローズボックス、アイコン、タイトル、クローズボックス……」とそれぞれ異なるUI要素が一列に並んでいるので、「アイコンにだけ注目する」とか「クローズボックスにだけ注目する」という事がやりにくいと僕は思っています。

タブの親子関係は、タブの色分けではなく、インデント幅というシルエットの違いで表現されています。これなら、2段階以上のネストであっても状態を正しく把握できるでしょう。

視覚的な情報の整理の仕方はデザインの本を学ぶと色々と情報を得られると思います。自分は一時期Webデザイナーになりたいと考えていたので、DTP的な記事が多く載っていたWebデザイン雑誌も何度か目にしていたのですが、上記のような話はそういった所で仕入れた物のような気がします。

学習コストを低くするためには

ヒューマン・インターフェースのデザインのセオリーという物がいくつかありますが、それらはソフトウェアにおけるインターフェースのデザインにも適用できます。

見た目の工夫

何のための物か、何を表している物なのか、説明がなくても一目で分かるようなデザイン。形がそれ自身の役割を表す。これはUIのデザインでよく言われる事です。

ソフトウェアの場合は、まずそのOSにおける一般的なデザインの流儀に則ってUI要素をデザインしておけば、少なくとも「ここはクリックできる場所なのだな」といった事を伝えられます。その上で適切なアイコン画像を加えましょう。基本はやはり重要です。

見えているUI要素はそのまま使えるようにする、という事も大事です。「見えているのに使えない」「見た目通りには動かない」というのは、ユーザを惑わせるばかりの害悪です。例えば以下のような物は論外でしょう。

  • グレイアウトされていないのに、クリックしても何も反応しないボタン。
  • グレイアウトされているのに、クリックを受け付けるボタン。
  • いかにも押せそうな風に出っ張った視覚的なデザインであるにもかかわらず、ボタンになっていない。

基本的に、人は他の場面で憶えたやり方を別の場面でも使いたくなるものです。タブを掴んで移動できる、という体験をExcelでやった後であれば、Firefoxのタブも掴んで移動できると考えておかしくないでしょう。UIの基本的なルールを統一しておく事の意義はそこにあります。

ですので、奇をてらってワケの分からないUIにするよりも、まずは既存の類似のソフトウェアの挙動に合わせる事ユーザがこれまでに学習してきた事に反しないようにする事。これをまずは意識しておくのが大事です。AndroidアプリのUIガイドラインなど、各OSで何らかのデザインのガイドが提供されているのであれば、目を通しておいて損はないです。

ツリー型タブも、タブをドラッグ&ドロップした時の挙動はAdobe Illustratorのレイヤーの操作をモデルに整備しました。また、マルチプルタブハンドラも「Ctrl-クリックでタブの選択状態をトグルする」「Shift-クリックで複数のタブを一気に選択する」という、Windowsやなんかで一般的な操作で使えるようにしてます。こういうのも、既存の物に合わせている例ですね。

見た通りに使えるかどうか、という観点で「こりゃあかんわ、好きになれんわ」と自分が最近感じたUIは、以下の2つのアドオンです。

これらはいずれもFox Splitterと同ジャンルのアドオンで、Firefoxのブラウズ領域を複数に分割してそれぞれに別々のページを表示できるようにする物です。

実際インストールして試してみると分かると思いますが、これらはどちらも、ウィンドウの上の方にあるタブバーやナビゲーションツールバーという操作UIが、タイル表示されたWebページの間で共有される設計になっています。下のペインで「戻る」操作をしたければ下のペインにフォーカスしてから上のツールバーの「戻る」ボタンをクリックする、という具合に、操作の対象と操作のために入力UIがバラバラに切り離されてしまっています。

また、タブと対応するWebページとが離れてしまっているのも問題です。どのタブをクリックしたらどのコンテンツ領域がフォーカスされるのか、どのコンテンツ領域をクリックしたらどのタブがフォーカスされるのか、今どのコンテンツ領域にフォーカスが当たっているのか(フォーカスされているコンテンツ領域の周りには枠が表示されますが、背景色によっては枠がとけ込んでしまう)、といった事を、このUIだとぱっと見て判断しにくいです。慣れれば使えるのかもしれませんが、これに慣れたくはないなあ、というのが僕の正直な感想でした。

UIが常時見えている事、表示UIが入力UIでもある事

入力UIが状態の表示のためのUIを兼ねる、というのもUIのデザインでよく言われるセオリーです。

  • 音量のボリュームをいじるダイヤルは、回した角度が入力となり、また、ボリュームの角度がそのまま音量を示すインジケータになる。
  • ガスコンロのつまみなら、回した角度が入力となり、同時にその角度が火の強さを示すインジケータになる。

ソフトウェアの場合もやはり同じ事が言えます。例えばクリックする度に機能の有効・無効を切り替えるトグル式のツールバーボタン(XULでは<toolbarbutton/>要素)であれば、これはチェックボックス型(<toolbarbutton type="checkbox"/>)としておきましょう。チェックボックス型のツールバーボタンは、1回クリックすると押し下げられたままの見た目で固定され、もう1度クリックすると出っ張った状態に戻ります。これは、入力装置であると同時に、見た目で今の状態を表すインジケータとなります。

ツリー型タブの場合も、タブという元々入力と状態の表示を兼ねたUIであった物を、そのまま少し形を変えて縦に並べています。

使用頻度の高いUIについては、常時見えている事も大事です。クリックしないと出てこない物は、そのワンステップが煩わしくてそのうち使われなくなってしまいます。Firefox 4から標準搭載されているPanoramaもこの問題を抱えていますし、Google Chrome版のTree Style Tab(※作者は僕ではないです)も、Chromeの拡張機能向けAPIの仕様上の制限でそのようになってしまっています。パネル型でもいいので、これを表示したままの状態に固定できるようにならないと、常用するUIとしてはちょっとキツいと自分は思います。僕が自分でツリー型タブをChrome向けに移植しないのは、この点をクリアする方法がまだないように見えるからという理由もあります。

カーソルを合わせたら自動で出てきて、カーソルを外したら自動で消える、という物は、場合によっては有用です。

  • 意図しないタイミングで出てきてしまえばストレスになる。
  • 出てきて欲しいのになかなか出てこない(例えば、表示するために1ピクセルの幅の領域の上を正確にポイントしないといけないとか)のもストレスになる。

「自動で隠す」系のUIは、WindowsのタスクバーやGNOMEのGNOMEパネルのような、画面全体の一番端に貼り付くUI以外ではあまり実用的ではないと僕には思えます。(余談ですが、UI要素は大きければ大きいほどそれを操作しやすく、画面の端であればどこでも反応するというボタンやUI要素は「無限の大きさを持っているに等しい」とよく言われます。Windowsでウィンドウを最大化した時に画面の右上にマウスのポインタを移動させてみれば、大雑把に指し示しただけで「閉じる」ボタンがハイライトされる事が分かると思います。)

モーダルよりもモードレス

これは1つ前の話とも少しかぶるのですが、「入力するモード」と「それ以外の操作をするモード」という風な排他的なモード切り替えは、極力避けるべきだというのが僕の考えです。設計を見直して、そもそもモードの切り替えが必要ないようにする、くらいに突き詰めていいと思います。

モーダルなUIは、ユーザの持つメンタルモデルの中にモードの違いがキッチリ組み込まれていればいいのですが、そうでない場合(ユーザのメンタルモデルの構築に失敗している場合)には混乱の元になります。いつもやっている操作を違うモードでやっても何も反応しない。でもユーザは、モードが違うせいでそうなっているという事に気付かない。「違うモードなのでその操作はできませんよ」と警告を出しても、根本的な解決にはなりません。

この観点で僕がどうしても好きになれないソフトウェアの代表例が、viとかvimとかVimperatorとかそのあたりという事になります。vi系のエディタはコマンドモードと編集モードを行き来しながら操作するという設計になっていて、この種のストレスを自分はしょっちゅう感じます。

単機能・明確なコンセプト

これは「UI」というよりも、もっと前の段階のテーマ決めの話になるかも知れません。

「何でもできる」という謳い文句は、「何をすればいいか分からない」という問題と表裏一体です。何をするための物なのかとか、どう使うべき物なのかとか、それを使う事で自分の生活がどう変わるのかとか、そういった事が伝わってこないとユーザは戸惑ってしまいます。先程、視覚的なデザインによって目に飛び込んでくる情報を制限して情報量を抑えるという事を述べましたが、コンセプトの設定にも同じ事が言えます。

「これができる」「これをする物だ」という事がはっきり見えていればいるほど、メリットが見やすくなるのと同時に、どういうデメリットがあるのかも見やすくなります。基本的にアドオンのインストールには多かれ少なかれデメリットがつきまとっていますが、そのデメリットを乗り越えてでも欲しい機能があるのだという人と、そういうデメリットがあるのであれば絶対に使いたくないという人とをきちんとスクリーニングできれば、ユーザを無駄に不幸にさせずに済むというのが僕の考えです。

カスタマイズ性の高い設計にしていたとしても、というか、カスタマイズ性が高い場合にこそ、既定の設定は重要です。第一に想定しているユーザ、この人にまずは使ってもらおうと思っている相手が、違和感なく使えるような設定をデフォルトにしておきましょう。インストールした後必ず自分に合わせた設定の変更を行わなくてはならないのでは、使い始める時の心理的コストが大きくなってしまいますし、そもそも、使う前から「どういう設定が望ましいか」をユーザが判断するというのが土台無理な話です。

また、最近はいろんな機能を1つのUIに統合する事が流行っているような感じがあると思いますが、「何でもできるUI」として1つのUIに2つも3つも機能を詰め込んでしまうと、実際の利用時に却って不便になる事もあります。

Firefoxのロケーションバーと検索バーを統合して「普通の単語を入力したらGoogleで検索して、URLっぽかったらタブを開いて……」という風な「文脈に応じた自動判別」を行うようにしたとして、「google.comという単語を検索したい」という意図をそのUIは正しく受け取れるでしょうか? 文脈の機械的な自動判別には今のところ限界があるので、誤判定、いわゆる「誤爆」の発生はゼロにはできません。

じゃあ考えられる候補をすべて一気に列挙してしまおう、というのも乱暴すぎる話です。入力欄に何か語句が入力されたら、検索結果を3件、その下に過去の履歴で入力とマッチした物を3件表示する、とした場合、ユーザが最初から「過去に見ていたページをもう一度見たくて」その入力を行っていたのであれば、最初に出てくる検索結果3件はただのノイズになってしまいます。ユーザがその時したい事に対して適切な結果が帰ってこないのは、単純にストレスですよね。

ある機能の利用頻度が特に高いのであれば、その機能には専用のUIを割り当ててやった方がいいです。よく使われている物を無理矢理他の物と統合するというのは、信頼性の低い自動判別を無駄に1枚噛ませるだけになったり、メニューを選ぶための手間を無駄に1つ増やすだけになったりという事になると思うので、僕はなるべくそういう事は避けたいと考えています。

Appleは、コンセプトをはっきりさせるという事を非常に強く実践しています。例えばiPodは非常に割り切った設計で「音楽を聴く」事に特化していて、関係ない要素をガンガン省いていました。それによって、「これは音楽を聴く物なのだ」という事が嫌でもユーザに伝わります。Appleの場合はスティーブ・ジョブズが「これがいい」と言った物を会社を挙げて製品にしており、製品の第1顧客はいつもスティーブ・ジョブズだと言えます。また、キングジム社のポメラも、会議の場で商品の企画が出た時にはほとんどの人が反対したけれど、1人だけ「買いたい」と言った人がいたので商品化できてヒットに繋がったといいます。(余談ですが、リンク先の記事によるとその1人というのは慶応大学の印南教授だそうです。何とも奇遇ですね。)

あらゆる人の方向を向こうとして誰の方向も向けないよりも、誰の方向を向いているのかがはっきり分かるようにした方がいい。100人を満足させようとしてみんなに「ふーん、悪くないね。まあ機会があれば試してみるかもね。」って言われて実際にはそのままスルーされてしまうよりも、99人にそっぽを向かれてもたった1人のユーザに「これすごくいい!!」と飛びついてもらえる、その人を確実に満足させられる方がいい。というのが今の自分の考えです。これだけ物や情報が溢れている世の中では、そうやって製品の特色をはっきりさせないと、評価してもらう前の段階で埋没してしまうのではないでしょうか。

これらの点で僕が「駄目だなー」と思っているのが、かつてのTBETab Mix Plusといったオールインワン型の多機能アドオンです。メリットを一言で説明しにくいから紹介する側も「とりあえずこれ入れとけ」という風な言い方にならざるを得ず、紹介された側はどこが具体的にどう変わるのか・どのようなデメリットがあるのかをきちんと把握できず、それのせいでトラブルが起こったとしても「何をするためのアドオンを入れたからこうなった」という事が全く分からないから原因を切り分ける事もできず、という負の連鎖が起こってしまいます。

先に入力を受け付けておいて、どうするかは後で選べるようにする。思考を途切れさせない。

僕が持ってる携帯電話は、待ち受け状態で数字をぽちぽち入力すると、その数字を電話番号として電話をかける以外にも、電卓機能を起動したり、積算メモ(簡易家計簿)に記入したり、という風な事ができます。メニューから「電卓」を起動して数値を入力するのでも、積算メモ機能を起動してから金額を入力するのでもなく、数字をぽちぽち入力したら画面の中で「この数字を電卓に流し込みたい時はこっちのボタンを押す」「この数字を積算メモに記録したい時はこっちのボタンを押す」という誘導が行われるんですね。

僕はどうも、そういうUIが好きみたいです。セカンドサーチは、Web検索バーで文字を入力した時に「既定の検索エンジンで検索するの? Amazonで検索するの? それとも英和辞書?」という具合に利用できる検索エンジンをポップアップで列挙して、文字入力からそのままスムーズに検索エンジンの選択に移れるようにする……というアドオンですが、前述の携帯電話のUIと考え方は共通していると思います。(なお、僕がセカンドサーチを作ったのはこの携帯電話を使い始めるよりずっと前でした。)

思い返してみると、セカンドサーチを作った動機は、「検索エンジンを選んでから検索して、また元のGoogleに戻して、という操作が死ぬほどめんどくさい。やってらんない。」という不満からでした。

エンジンを切り替えるのが面倒だから、大抵既定の検索エンジンで済ませちゃう。たまに検索エンジンを切り替えて使うと、その後無意識のうちに既定のGoogleで検索したくなって、しかし検索エンジンを切り替えたという事実をすっかり忘れていて、うっかり別の検索エンジンで検索してしまう。そういうのが鬱陶しくて、僕は結局Googleしか使わなくなってしまいました。でも、せっかくOpenSearchとかで検索エンジンを追加登録できても、それらを使う機会が全く訪れないなんて、こんな勿体ない事があっていいはずがない。そう思って、「先に検索エンジンを選ぶのと、後で元に戻すのがめんどくさいんだ」と判断して、「後から検索エンジンを選べて、既定の検索エンジンに戻す必要がない」という操作ができるようにしてみたんですね。

こういう傍目から見てアホとしか思えない行動を取ってしまう人はけっこういるんです。Web検索バーに文字を入力する時には、入力しようと思っている語句に注意がいっているから、「どの検索エンジンが選択されてるか」という事に注意が向かないんですね。そういう風な思考ができあがっている時に、期待通りの結果が得られないと、「なんでやねん」とストレスを感じてしまうわけです。

そういうミスに対して「それはあんたの使い方が悪いんだ」と責める人もいるでしょうけど、道具は使う人のためにデザインされるべき物と考える限りにおいては、人がそういう行動を取ってしまうのなら、その行動に合わせて道具をデザインした方がいいと僕は思っています。

ユーザの行動や入力をトリガーにする

1つ前の話を別の観点からもう1回語ってみます。

金額の事だけで頭がいっぱいになっていて、とりあえず無意識に数字を入力し始めてしまう、という僕の行動をトリガーにして、僕の携帯電話はよさげな機能をサジェストしてくれるわけです。同じようにセカンドサーチも、頭の中が調べたい単語の事でいっぱいになっていてとりあえず無意識に単語だけ入力してしまうという僕の行動をトリガーにして、適切な検索エンジンを後から選べるようにサジェストしてくれます。このように、無意識の行動を起点にして各機能を呼び出せるようになっていると、「機能をどこから呼び出すのか」を改めて考えなくて済みます。

機能をどこから呼び出すのか、というのは結構重要な問題です。

メニューを何階層も辿った奥にある機能というのは使うのが億劫なので、だんだん使わなくなってしまいます。しかし、だからといって階層の浅い所にメニュー項目を増やしていったり、ツールバーのボタンをどんどん増やしていくと、機能が増えていった時に収拾が付かなくなってしまいます。

WindowsのコマンドプロンプトやLinuxやMac OS Xのターミナル(端末エミュレータ)のようにコマンドを入力させる形式なら表示領域を悔いませんが、今度は、ユーザが「どんなコマンドが使えるのか」という事を常に頭の中に入れておかないといけないようになってしまいます。コマンドだけじゃなく、今どこのディレクトリにいるのかとか、ログインしているユーザが誰なのかとか、いろんな「モード」を把握してないと使えません。僕はそんなの全部は覚えてられないので、CUIでコマンドライン入力というのは基本的に好きじゃないです。

表示領域も食わないし文字列のコマンド入力よりも直感的、という事でマウスジェスチャ(リンクをドラッグしたままマウスを上下左右に動かすと、その軌跡(ジェスチャ)がコマンドとして解釈される機能)はどうなんだ? っていう話になってきますけど、マウスジェスチャも「ジェスチャを覚えないといけない」という問題はやっぱりあります。上上下下左右……みたいなややこしいジェスチャを全部覚えてられるかというと、まあ無理な話です。実際、マウスジェスチャを使ってる人でも「憶えてるのは上下左右の各方向にマウスを動かす単純な動き程度でそれより複雑な物は全然使わない」と言ってました。

という話の中にも出てきていますが、ごく簡単なジェスチャだったらアリだと言えます。リンクを引っ掴んで適当にぽいっと投げたらそれをタブで開く、とか、その程度の大雑把さなら苦になりません。ただ、この場合は「ジェスチャを入力している」と言うよりも、「リンクというオブジェクトを掴んで何かしようとしている」という場面だと解釈した方が正しいでしょう。

僕が「ユーザの入力をトリガーにする」という言葉で表現したかったのはそういう事です。何かキー入力を始めたとか、何かオブジェクトがドラッグされたとか、そういう行為そのものをトリガーにするっていう事であって、「どういう文字が入力されたのか」とか「どういう風にマウスを動かしたのか」とかの細かい所を情報として使うという話ではないんです。もちろん、入力された内容にそぐわない機能を除外した上でサジェストする(例えば数字だけが入力されていたら英和辞書は候補に出さないとかの)工夫はあってもいいと思いますが。

「冷蔵庫に卵とトマトがある事を確認して、それからクックパッドで卵とトマトを使ったレシピを探そう」という風な理路整然とした行動計画を、現状から目指すゴールまでを最初から完全にきちんとイメージできる人ばかりではないんです。というか僕自身がそういう事ができない方なんですね。おなかすいてとりあえず冷蔵庫を開けてみたとか、そういう無駄な事をやってしまう方です。

そういう最初のアクションを無意識レベルで起こした結果、機能がサジェストされたり視覚的なフィードバックがあったりして、そこからさらに「そういえば自分はこういうことをしたいんだった」と次の行動が喚起される。(もっと言うと、その時の既定の挙動が一番利用頻度の高い物になっている。)という風な誘導がウザくないレベルで働くようなUIが、僕にとっての「良いUI」なんでしょうね。

ブラウザのUIはゲームのUIではない

ちょっと話はズレますが、ストリートファイターとかの対戦格闘ゲームを考えてみましょう。この種のゲームは、技を出すための複雑なコマンドを覚えたり、覚えたコマンドを適切なタイミングで正確に入力できるようになったり、という努力の末の「上達」が「勝利(報酬)」に結び付くというゲームのデザインになっています。勝てるようになれたら嬉しくて、負ければ悔しくて、なのでみんな必死になってコマンドを覚えるし、正確に入力できるようになろうとする、そういうモチベーションがある。

翻ってブラウザのUIという物を考えてみると、誰が好きこのんで複雑なコマンドを覚えたくなるの? ブラウザを上手く使えるようになる努力をして、上達して、それのどこが嬉しいの? って話なんですよ。普通のユーザにとって、ブラウザとかUIとかってそんな努力を費やす対象ではないです。勉強しないとまともに使えない斬新な文房具とか包丁とか、使いたくなりますか? なりませんよね。普通の人にとってのブラウザって、そういうレベルの物でしかない。

UIをデザインするんだ!って思って頑張る時に勘違いしてしまいやすいのはそこなんですよね。こんだけ頑張って斬新なUIを考えました、他に類を見ないUIになりました、ただし使うのにはそれなりに慣れが必要です、っていって作った物をユーザに見せても相手にされないですよ。そんなの作り手の自己満足でしかない。自分にとって物作りそれ自体が楽しくなってきた頃に犯しがちなミスです。

実用品のUIと、娯楽だったり趣味の物だったりのUIとは、別の物として考えて欲しいです。日常的な利用にゲーム性を加えてみましたとか、普段の利用がちょっと楽しくなりますとか、たまにありますけど、それで本来の用途に支障をきたしたりストレスが増したりするようになってしまっては本末転倒です。

自分の部屋とかキッチンとか

自分が生活する部屋や、日常的に使うキッチンの事を考えてみて下さい。

  • よく使うものは奥にしまわない。流しの下を開けたらすぐそこに包丁があるとか、毎日使う茶碗は引き出しの手前に入れておくとか、そういう風に自然となってる。逆に、奥の方にしまい込んだ鍋とかは、出すのが面倒でほとんど使わないという事も結構ある。
  • どこに何があるか、自分にとって分かりやすいような配置に落ち着いてるはず。
  • どこに何を置いたか、だいたいは把握できている。こういうことをしよう、と思った時にどこに手を伸ばせばいいかは無意識に判断できる。

ソフトウェアのUIも基本は同じだと思います。

よく使うものを手前に置くとかの話はここまでで述べた話に通じています。ここで新しく述べたいのは、「どこに何を置いたかだいたい把握してるはず」という部分です。

ロケーションバーと検索バーの統合という風に、最近は(主に表示領域を広く取るために)複数のUIを1つにまとめる風潮があるみたいなんですが、そうすると使う時に余計なステップが増えてしまいかねないというデメリットがあります。UIをどんどんまとめていくという事に固執しないで、時にはUIを分けるという判断も必要だと僕は思っています。「使い方を頑張って覚えなきゃいけない様なUIは駄目だ」という風な事を前述しましたが、並んでる物を使い分ける程度の事は大抵の人にはできるはずです。あんまりユーザをなめんなよ、ということですね。URLを入力したい時にはロケーションバーをクリックして、検索したい時は検索バーをクリックして、という事をユーザが無意識にできるのであれば、そこはUIの設計に組み込んで活かしてもいいはずです。

あと、キッチンに例えるついでに言うと、キッチンを清潔に保った方がいいのと同じでソースコードも清潔にした方がいいです。詳しくは実装の話で述べますが、生ゴミを放っておくと腐って虫が湧くように、汚いソースコードも放置すればバグの温床になりますので。

人は自分の行動パターンを変えようとしないという事

一般的に言って、フツーの人は「どうしても必要だ!」という強烈な動機がない限りは新しい物の使い方を積極的には覚えようとしませんし、いつも取っている行動のパターンも変えたがりません。というか、無意識のうちに同じ行動を取ってしまいます。そこから意識して外れようとすると、これはストレスになります。何度も述べていますが、「素晴らしいUIを作ったから、ユーザは使い方を覚えるために苦労してくれるはずだ」というのは作り手の傲慢なんですね。そんな物は、そのうち使われなくなってしまうのがオチです

ただ、あんまり人間の順応性をナメすぎてもいけません。最初は違和感があった「いつもと違う行動パターン」でも、そのうち慣れちゃうというのは結構あります。そこを考慮から外してしまうと、常用するのがウザいUI(例えば、いつまで経っても毎回馬鹿丁寧に「どうしますか?」と聞いてくるような)になってしまいます。

  • 今まで慣れ親しんできたものと同じ要領で使えるようにする。
  • 同じ要領では使えないものでも、なるべく早く慣れる事ができるようにする。
  • 慣れてしまった人に余計なストレスを与えないようにする。

これが大事なんだ、「どこまで丁寧にやってどこからはユーザの慣れに期待するか」のバランス感覚が必要だ、と僕は思っています。

この観点から、僕はKDEでのファイルのドラッグ&ドロップの操作は「馬鹿丁寧すぎ」の方に入るのかなーと思っています。Linuxのデスクトップ環境の1つであるKDEでは、ファイルを別の位置にマウスの左ボタンでドラッグ&ドロップすると、必ずメニューが出てきて「コピー」「移動」みたいなその時可能な操作を選べるようになっています。これ、最初はいいなって僕自身思ってたんですが、使ってるとだんだんうざく感じるようになってしまいました。「上の階層のフォルダにドロップしたんだから、コピーじゃなくて移動したいに決まっとるがな!」「新しくフォルダ作ってそこにドロップしたんだから、移動したいに決まっとるがな!」と、自分の場合は少なくとも、ファイルのドラッグ&ドロップは「移動」のためにやる場合が圧倒的に多かったんですね。それなのに毎回「コピーですか? 移動ですか?」って訊かれる。これがそんなにストレスになるとは、実際使い続けてみるまで僕には分かりませんでした。

なので、セカンドサーチは何も検索エンジンを選ばなければ既定の検索エンジンで検索しますし、マルチプルタブハンドラも、「グッ」と押し込む感じで敢えて長くタブの上でボタンを押し続けない限りはタブの選択操作が始まらないようになっています(このタブ選択操作の挙動はユーザからの提案で実装したものですが、採用して大正解だったと思ってます)。

ユーザの「言う事」に振り回されない・惑わされない

「ユーザからの提案を取り入れて正解だった」と書いた直後に述べるのも何ですが、ユーザの提案を何でもかんでも呑んでしまうのは避けた方がいいと僕は思ってます。

ユーザは基本的に自分の不満を素直に言ってくるもので、その提案を取り込んだ結果他のユーザにどういう影響があるかとか、実装がどう変わるかとか、そんな事までは考えてないと思っていいと思います。そういう提案をどんどん取り込んでしまうと、最初に定めたはずの「これは何をするためのソフトウェアだ」というゴール設定がブレてしまう事にもなりかねません。なので、僕はユーザからの提案に対しては、最初に決めたコンセプトに沿っているか・既存の物を壊してしまわないかという事をなるべく考えて、折り合いが付かなければ「それは取り込めない」と回答するようにしています。

タブブラウズの機能を何でもかんでも拡張するTBEというアドオンを作っていた時は、僕はわりと何でも提案を取り込んでしまってましたが、その結果どうなったかというと、ソフトウェアが肥大化するわUIが複雑化するわコードがごちゃごちゃになるわで散々でした。これは、当時の僕が名誉欲だとか人に感謝されたい欲だとかに突き動かされていたからという理由だけでなく、ソフトウェアのコンセプトが曖昧だったので、何を入れて何を外せばいいのかという判断がそもそもできなかったせいでもあるんじゃないかと、今では思ってます。

コンセプトがはっきりしていると、寄せられた意見を取捨選択しやすいです。意見を退ける時も、「それはコンセプトに合わないから」とはっきり言える。好き嫌いだとか意地悪だとかで言ってるんじゃないという、ある意味では言い訳を自分に対してできるんですね。八方美人タイプだと人の頼みを断る事自体がストレスになってしまいますが、こうすれば罪悪感を感じなくて済みます。

ということでNOと言う事の大事さを散々説いたのですが、かといって頑なになりすぎるのも良くないです。ユーザ1人だけが言ってきているのならまだしも、同じ要望・不満が別々のユーザ10人から飛んでくるようだと、これはユーザの使い方ではなくてUIの方が(ひょっとしたらコンセプトも)悪いという可能性を疑った方がいいでしょう。「なんでみんな理解してくれないんだ、こんなに素晴らしい物なのに!!」という思い上がりに囚われてしまってはいけません。

あと、意見を取り入れる時も、取り入れ方は工夫する必要があると思います。例えば「ここにこういうボタンが欲しい」という要望が来た時に、本当にそのまま言われた通りにボタンを追加する前に、なんでそこにボタンが欲しくなったんだろうかという事を考えるという事です。そこで考えた結果、やっぱりボタンを追加した方がいいという結論に辿り着くかも知れませんが、ボタンを追加しなくても別の方法で解決できるという事が分かるかも知れませんし、コンセプトの見直しを図るきっかけになるかも知れません。

余談ですが、Microsoftは製品を開発する時に、ユーザの言葉を聞くんじゃなくて、ユーザがその製品をどう使おうとしたかという様子を観察して製品にフィードバックするという事をやっている、という話を以前にどこかで読みました。ユーザ自身が自分の要望や不満を100%正しく言語化できるわけではない、ユーザ自身が気付いていない問題や視点があるのかも知れない、恥ずかしくて嘘をついているかも知れない、だから行動を見る……という話だったと思います。

Microsoftと同じ事をやるにはお金も手間もかかるのでそのままマネするのは難しいですが、そういう考え方は持っておいていいと思います。

セオリー

僕がここで述べた事は、多分UIのデザインのセオリーと言われるような事ばかりです。名前を挙げた自作のアドオンも、最初からそういう理屈を考えて作ったというよりも、試行錯誤してるうちに辿り着いた結果を後から分析してみたら案外セオリーに則っていた、という感じです。もっとちゃんと体系立ててUIのデザインの理論を勉強してから臨んでいたら、もっと少ない労力で答えに辿り着けたのかも知れないなあと思っています。

セオリーにはセオリーと呼ばれるだけの理由がちゃんとあると思いますので、我流で突っ走る前に一応は基本を抑えておくといいんじゃないでしょうか。

実装上の工夫やテクニック、コンセプトを具現化する時の注意点

プログラムとしての作りやすさに引きずられない

人にやさしい・使いやすいUIを実現するためには、プログラムとしては複雑な物になってしまいがちです。逆に、プログラムとして簡単な物にしようと思うと、エンドユーザにとっての使いやすさが犠牲になってしまいがちです。

「Now Loading…」系の物なんかは、その代表例ですよね。プログラムを作る側としては、必要なデータが全部揃うまで待ってから最後に一気に処理した方が、コードとしてはシンプルに書けます。しかし、これではエンドユーザは待たされている間何もできません。今では考えられない事でしょうが、昔のブラウザもまさにそういう設計でした。ページの内容を全部インターネット経由でダウンロードしてくるまで、ページの描画をしてくれなかったのです。

今のブラウザはそんなことは無いですよね。読み込みが少しずつ進行するに従って、ダイナミックに表示を更新して、現在までに読み込みが完了した部分から順次表示してくれます。多少作るのが面倒であっても、こういう風な設計を心がける事はとても大事だと思います。

ただ、そのようにユーザにとっての使いやすさを追求するために、プログラムとしてのコードの綺麗さを犠牲にしすぎるのも良くないです。コードの見通しが悪くなってしまうと、いざ挙動がおかしい所を見つけたとしても、どこをどのように直せば良いのか見当が付かなかったり、ある所を変更したせいで別の所に意図しない影響が発生してしまったりするため、それ以上コードに変更を加えられない(ちょっとでも変更したらぶっ壊れてしまう)、みたいな事になってしまいます。

ユーザにとっての使いやすさを大事にする事と、プログラムとしての見通しの良さを高く保ってメンテナンスしやすくしておく事は、頑張り次第で両立できます。そのためのノウハウを、ここで少しだけご紹介しようと思います。

Firefoxのアドオン開発における、避けるべきパターン

Firefoxのアドオン開発では、XMLとJavaScriptの組み合わせで「要素の振る舞い」を定義しておくXBLという技術によって「独自のタグ」のようなものを定義できます。しかし、メンテナンス性を高く保つという観点からは、XBLの利用はあまりお勧めできません。使い所をわきまえればXBLはそれなりに便利な技術ではあるのですが、「Firefoxのアドオン」の開発においては、便利さよりもデメリットの方が大きいと僕は思っています。

実際、僕は上述したアドオン「Fox Splitter」の旧バージョンをXBLを多用して開発してきましたが、XBLのせいで全体として見通しが悪くなってしまっていたり、開発時の構成に強く依存したコードがJavaScriptとXBLに散らばっていたせいで調べなければいけないコードの範囲が無駄に広がってしまったりしていたせいで、ドツボにハマってもはや自力ではメンテナンスできなくなってしまい、1年半もの間完全に放置することになってしまいました。

前述した話ともかぶりますが、不必要な多機能化も避けた方がいいです。ある機能Aと別の機能Bとで共通の処理があるから、AとBと共通の処理を1つのアドオンにまとめておこう、という風な考えに至るのはごく自然な発想だと思いますが、しかしAとBがそれぞれ全然関係の無い機能なのであれば、共通の処理を2回書く事になったとしても、AとBは別々のアドオンとして分けて開発する事を僕は強くお勧めします。

今はAとBで共通の処理を使っているとしても、Aの機能とBの機能のそれぞれのコンセプトを突き詰めていくと、共通の処理にできる部分はほとんどなくなってしまうかもしれません。にもかかわらず、「AとBとそれらの共通部分」という構成のコードがあると、この構成を維持する事に発想が囚われてしまって、AもBもコンセプト的に中途半端なままになってしまうのではないでしょうか。別々のアドオンに分けて開発していれば、そういう風に今ある実装に引きずられないで、コンセプトを突き詰めた開発をしやすいと僕は思っています。

他に思いつく事としては、ありきたりですが、プログラミングにおいて一般的なアンチパターン(これはマネしちゃいけない、という反面教師的なパターン)を避ける事がやはり大事だと思います。

例えば、1つのクラスに2つも3つも関係のない機能をまとめてしまうと、これは先ほど述べた「アドオンの多機能化」と同じような問題に繋がりかねません。それを避けるには、個々のクラスの実装が受け持つ機能の範囲を定める形で、実装を適切な粒度に分けておく事が大事です。

また、3項演算子や、論理演算子の優先順位を逆手に取ったプログラミングなどのトリッキーな書き方も、あまり多用するべきではないです。トリッキーなコードは芸術的で見ていて美しいものですが、あまりに芸術的すぎるコードは、非常に限定された条件下でしか正しく動かず、手を少し加えただけで動かなくなってしまう事もあったりして、その後の機能拡張やメンテナンスに対して脆弱になってしまいます。芸術品を作るのではなくて、実用品を作ろうとしているのだ、という事を常に念頭に置いておく事を僕はお勧めしたいです。

1年後の自分が読んでも意味が分かるようなコードにする事を心がける

1つのプログラムを1人で集中して開発している時は、プログラムの全体像が頭に入っていますから、多少読みにくいコードでも開発する事ができます。

しかし、誰かに手伝ってもらうとしたらどうでしょうか。あるいは、1年間そのプログラムの事を全く考えずにいて、1年後に急に開発を再開する事になったとしたら(1年後の自分なんて、はっきり言って他人も同然です)。読みにくいコードになっていると、「この関数は何のための物なんだろう……」とか「なんでこんな設計になっているんだろう……」といった感じで、全体像を把握できなくて何も手出しできなくなってしまいます。また、そういう状態で不用意に既存のコードを書き換えると、思わぬ副作用が発生して、今まで動いていたものが全く動かなくなってしまうかも知れません。これでは開発になりません。

前述した「1つのクラスに2つも3つも機能が入ってしまっているコード」や「あまりに芸術的すぎるコード」も、そういう問題を引き起こしがちです。そういった問題を避けるための、「1年後の自分が読んでも分かるようなコードにするテクニック」をいくつか紹介しましょう。

変数名やメソッド名、クラス名を分かりやすくする

変数やメソッド、クラスの名前は、それが何を表しているのか・何をするための物なのかをきちんと表す物にしましょう。例えば以下のようなコードは最悪ですね。

var bool = true; // 変数名が「真偽値である事」だけしか表していない

function f() { ... } // 関数に適切な名前が付いていない

これは、以下のような書き方をした方がいいです。(これはあくまで例です。表す内容がこれとは違う場面であれば、その都度適切な名前を付けましょう。)

var enabled = true; // 変数名から「何かの機能が有効か無効かを示すものだ」という事が分かる

function openTabAndInitialize() { ... } // 関数名が処理の内容を表している

ただ、名前に動詞や形容詞、前置詞などが2つも3つも入ってくるようだと、いくら処理の内容をきちんと言い表していても駄目です。関数や変数に簡潔明瞭な名前を付けられないのは、そもそも設計が悪いからと考えられます。きちんと設計してあれば、関数や変数には大抵の場合、ちゃんと簡潔明瞭な名前を付けられるのです。ですから、この例のopenTabAndInitialize()だと以下のように設計し直す事になるでしょう。

function openTab() { // 2つの小さな処理単位からなる、1つの大きな処理単位
  var tab = openNewTab();
  initializeTab(tab);
}

function openNewTab() { ... } // 新しいタブを開く、という1つの小さな処理単位

function initializeTab(aTab) { ... } // タブを初期化する、という1つの小さな処理単位

Rubyというプログラミング言語の開発者のMatz氏の言う「名前重要」というスローガンは、この事を指しています。変数や関数に名前を付ける時はちゃんと考えてから付けないと駄目で、名前付けに困る時は設計を見直す事も視野に入れるべき、という事ですね。

データに意味を持たせない。

データを表す時に、配列の1個目の要素が名前で、2個目の要素がデータの数を表して、3個目の要素がアイコンのサイズを表して……という風な作りにしてしまう事があります。

var data = ["foo", 11, 32];

こういうデータの設計はやってはいけません。「何番目のデータがこういう意味である」という風な、データの順番などがそのまま意味を表すような設計だと、順番をいちいち細かく覚えてられませんから、うっかりミスで間違えてしまいやすいです。また、こういうデータの設計だと、データ構造も変えにくいです(最後にどんどん新しい情報を付け足すというような、やっつけ仕事の解決策しか取れない)。

こういう物は、連想配列とかハッシュとか言われる形式でデータを表現する方がよいです。

var session = {
      title     : "foo",
      tabsCount : 11,
      size      : 32
    };

連想配列やハッシュであれば、ハッシュのキーがその値の意味を表すメタ情報になります

引数の多い関数を作らない

1つ前の話と同じ事なのですが、以下のように関数の引数が3つも4つもあるような関数は作るべきではないです。関数を呼び出す時に、何番目にどの情報を渡せば良いのかを間違えやすくなってしまいます。

function load(uri, title, size,
              referrer, ...)

こういうものは、ハッシュを1つだけ引数に取り、そのハッシュの値が個々のパラメータを表すという設計にしておきましょう。

load({
  title    : "foo",
  uri      : "http://...",
  size     : 32,
  referrer : null
})

このようになっていれば、引数の順番を意識しなくて済みます。

自動テストを作っておく

自動テストとは、ある関数や機能について「どういう呼び出し方をした時に、どういう結果が返ってくるか」という事を確認するためのプログラムです。具体的には、以下のような「テスト関数」が沢山連なったものが「自動テスト」というプログラムになります。

function test_getMessage() {
  // 実装を実際に呼び出してみる
  var result = getMessage();
  // 返り値は期待値と一致しているか?
  assert.equal('expected message', result);
}

ある機能Aがあって、そのAに依存するBという機能があって、Bに依存するCという機能がある時に、Cが正しく動かなかったら、さてどこに問題があると考えれば良いでしょうか。Aが壊れているのかも知れないし、Bが壊れているかも知れないし、Cが壊れているのかも知れない、このままだと何が原因なのかは分かりません。

しかし、機能AとBは自動テストでちゃんと期待通りの動作をする事を保証されていて、今まさにCを開発している場面なのだとしたら、これはCに問題がある可能性が高いと言えます。このように、自動テストがある事で複雑なプログラムであっても一歩一歩着実に開発を進められるのです。

また、自動テストは、その関数や機能が期待通りに動くかどうかを検証するものであると同時に、その機能はどのようにして使う物なのか、どういう結果が返ってくる物なのか、といった事の例にもなります。

遅延処理、非同期処理

プログラムは、上から順に1行ずつ読んで処理の流れを把握できるようになっている物ばかりではありません。ユーザの入力を待ってから次の処理を行うとか、読み込みが完了するまでの間別の処理を走らせておいて読み込みが完了したら画面を切り替えるとか、このような「人にやさしい挙動」を実現しようと思うと、上から順に1行ずつ読んだのでは処理の流れを追う事ができないような、分かりにくいコードになってしまう事を避けられません。

Firefoxのアドオン開発の場合は言語はJavaScriptを使う事になりますが、JavaScriptでは非同期処理や遅延処理が関係する場面だとコールバック関数(ある処理を呼び出す際に、その処理が終わった後で実行されるべき処理を関数として定義して渡すという物)を使わざるを得ません。そのような処理を2つも3つも連携させようとすると、コールバック関数を何十にも重ねる事になってしまいがちです。

例えば「新しいウィンドウを開いて、そのウィンドウの読み込みが完了したらコールバック関数を実行する」という例は以下のように書けます。

function openAndWait(aCallback) {
  var win = window.open(...);
  win.addEventListener('load', function() {
    win.removeEventListener('load', arguments.callee, false);
    aCallback(win);
  }, false);
}

これを使って「ウィンドウを1つずつ500ミリ秒おきに順番に3つ開いていく」という処理を書こうとすると、以下のようにコールバック関数をどんどんネストしていかないといけません。

openAndWait(function(aWindow) {
  aWindow.move(...);
  window.setTimeout(function() {
    openAndWait(function(aWindow) {
      aWindow.move(...);
      window.setTimeout(function() {
        openAndWait(function(aWindow) {
          aWindow.move(...);
          ...
        });
      }, 500);
    });
  }, 500);
});

2階層や3階層ならまだしも、これが10階層や20階層も重なると、インデント幅が増えすぎてワケが分からなくなってしまいます。また、開き括弧と閉じ括弧の間に沢山のコードが入るため、コード全体の見通しも悪くなります。

このような問題に対処するための機能が、jQueryにはdeferredという名前で搭載されていますし、同様の機能だけを提供するJSDeferredという軽量なライブラリもあります。ここではJSDeferredの使い方を少しだけ解説したいと思います。

JSDeferred

先の openAndWait() という関数は、ウィンドウの読み込みが終わった後に次の処理としてコールバック関数を実行する物でした。これをJSDeferredを使って書き換えてみた物が、以下の例です。

function openAndWait() {
  // (1) Deferredクラスのインスタンス(Deferredオブジェクト)を作る。
  var deferred = new Deferred();

  var win = window.open(...);
  win.addEventListener('load', function() {
    win.removeEventListener('load', arguments.callee, false);
    // (3) 読み込みが終わったら、返したDeferredオブジェクトの
    //     call()メソッドを呼ぶ。
    deferred.call(win);
  }, false);

  // (2) Deferredオブジェクトを返り値として返す。
  return deferred;
}

このように書き換えた関数は、以下のようにして「次の処理」を記述できるようになります。

openAndWait()
  .next(function(aWindow) {
    aWindow.moveTo(...);
  });

それどころか、さらにその先にもまだまだ「次の処理」を続けて記述できます。

openAndWait()
  .next(function(aWindow) {
    // 読み込みが終わったら実行
    aWindow.moveTo(...);
  })
  .wait(0.5) // 500ミリ秒待つ
  .next(function() {
    // 次のウィンドウを開く
    return openAndWait();
  })
  .next(function(aWindow) {
    // 読み込みが終わったら実行
    aWindow.moveTo();
  })
  .wait(0.5) // 500ミリ秒待つ
  ..

JSDeferredを使うと、何個も処理を重ねる場合でもコード上のネストがあまり深くなりません。また、コールバック関数を重ねる場合と異なり、コードを読む時に上と下を行ったり来たりする必要もありません。コールバック関数を1個目の引数に受け取るのか2個目の引数に受け取るのか、といったインターフェースの違いも意識しなくて済みます(全ての非同期処理を統一的なインターフェースで利用できるようになる、とも言えます)。

詳しい事はJSDeferred開発者のcho45氏自身による解説を読んで下さい。JSDeferredを使いこなせるようになると、表現の幅がぐっと広がります。

先に名前を挙げたアドオンFox Splitterも、JSDeferredに強く依存しています。Fox Splitterは新しいウィンドウを開いて位置や大きさを制御するという事をやっていますが、ウィンドウが開かれるのを待って次の処理に進んだり、ウィンドウの位置が確定するのを待って他のウィンドウの位置を調整したり、といった感じで「前の処理の完了を待ってから次の処理を行う」場面が非常に多いです。僕はJSDeferredのおかげで、そういった処理の前後関係を意識しないで複数の機能と機能を連携できるようになったために、Fox Splitterを無事完成させることができました。

前述した「ユーザの入力を一旦受け取って、入力が完了した後に次に進む」というような事も、JSDeferredを使えば比較的簡単に処理を記述できるでしょう。人にやさしいUIを作る上で、JSDeferredのようなライブラリは非常に役立ちます。

とりあえず作ってみるという事

UIのアイディアを思いついたら、あれこれ計画を練って検討するのもいいですが、さっさと実際にプロトタイプを作ってみることを僕はお勧めしたいです。

コンセプトを形にする事は重要です。形にして実際使ってみて初めて分かる事もあります。プランを練っている時には「素晴らしい」と思っていても、実際使ってみると「アレ?」って事はよくあります。手早くプロトタイプを形にして、コンセプトが正しかったかどうかを初期段階で確認して軌道修正をするのが、後で痛い目を見ないで済むようにするコツです。問題点の発覚が遅れれば遅れるほど、取り返しが付きにくいです。

ブラウザのアドオンは、そういう意味では格好の実験場だと僕は思っています。

これは、大学の卒業制作でMozillaの拡張機能として「こんなUIがあってもいいんじゃないか?」という物を作った時に考えた理屈なのですが、ブラウザのアドオンとしてプロトタイプを作る事にはいくつかのメリットがあります。

  • 既にあるソフトウェア資産を流用できる。いちから自分でブラウザを作るのは大変だが、アドオンとして作るのなら、ネットワークの通信だとかそういった部分を考えなくても済む。
  • ユーザに使ってもらう時の障壁を低くできる。今まで使ってきたWebブラウザの延長線上として、全く新しい別の物を使い始めるのに比べれば少ない学習コストで使ってもらえる。

Firefoxのアドオンの場合、ソースコードがオープンソースなライセンスで公開されている場合が多いというのもいい所です。分からない所があれば、やりたい事に近い事をやっているソフトウェアのソースコードをそのまま参考資料として参照できますし、ライセンスが定める条件に従ってさえいれば、そのままソースコードを流用する事すらできます。

ちなみに、「オープンソースの物を流用したら、その成果もいきなり全世界に公表しないといけないんでしょ? それじゃ秘密裏に実験的な事ができないじゃないか」という風に思う人がいるかもしれませんが、それは誤解です。例えばGPLなどのライセンスでは、ソースコードを流用して作ったソフトウェアのユーザに対してソースコードを開示する義務はあっても、ソフトウェアを渡されてもいなければ存在も知らないような人相手にまでソースコードを開示する義務はありません。安心して下さい。

デバイスの進歩について

質疑応答で少し話しましたが、ソフトウェアのUIとハードウェアの進歩は切っても切れない関係にあると思います。

「複雑なマウスジェスチャは覚えられないから使い物にならない、シンプルな動き以外はまともに使えない」という風な事を前述しましたが、MacやiPhone、iPadで可能な2本指・3本指でのジェスチャ(マルチタッチ)は、その制限を乗り越える技術です。指2本を開くような動き(ピンチアウト)で画面の拡大、指2本を閉じるような動き(ピンチイン)で画面の縮小、という風に、簡単でありながら表現力豊かなジェスチャ操作が可能です。これはハードウェア側のサポート無しには成り立たないUIです。

Panoramaはモーダルなせいでいまいち使いづらいですが、これはPCの画面が狭いという現在のデバイスの制約による所が大きいと僕は思っています。もしPCの画面が物凄く広ければ、あるいは、画面の外に空中に映像を投影するような技術があれば、Panoramaはモーダルにしないで常時表示しておけるかもしれません。

今あるハードウェアの限界の中で使いやすいUIを考える事も大切ですが、できない事はやっぱりできないので、そこは潔く諦めてハードウェアの進歩を待つといった判断も必要では無いかと僕は思います。あるいは、ハードウェアの制限に合わせる形でもっと別のUIを考えてみるとか。いずれにしても、今あるハードウェアの上では使いにくいと言わざるを得ない物を「理論的には使いやすいはずなんだ」みたいな感じでごり押しするような事はしないで、柔軟に考えるようにして下さい。

ターゲットユーザを誰にするのかという割り切り

僕の場合は、今は自分自身が第1のターゲットユーザだと考えています。自分自身が常用するものだからこそ、クオリティを維持して快適な状態を保ちたいと思える。というのが今の僕の考えです。

自分以外の人をターゲットユーザに想定するのもありだとは思いますが、僕の場合は既に20を超えるアドオンを開発していて、それぞれにバグ報告が来て修正のためにてんてこ舞いになっているというのが実情で、自分で使う物についてすら十分なメンテナンスをできていない状態にあります。自分自身を第1のターゲットユーザとして考えるというのは、コンセプトをブレさせないための方法論でもありますが、ユーザから寄せられる大量の要望から距離を置いて自分の身(精神)を守るための手段でもあるんですね。

誰をターゲットにする場合であっても、基本的な所はセオリー通りにやる事が大事なのだと僕は思っています。その上で、例えばお年寄りのための物にするなら文字を大きくするとか、使う言葉を平易にするとか、応用を組み合わせていく事になるのだ……と、僕は思っています。

道具を自分に合わせないと我慢できない人と、道具に自分を合わせるのが苦にならない人がいる(11時20分追記)

カスタマイズ性の高いブラウザだからみんなカスタマイズしたくなるかというと、そうとも言えません。統計として、Firefoxのユーザの全員がアドオンを使っている訳ではなく、また、アドオンを使っている人でもインストールしているアドオンの数は片手で数えられる程度である場合がほとんどだというデータが、過去のMozillaの調査で出ていました。カスタマイズ性の高い設計になっている事と、実際にカスタマイズして使われる事とは、あくまで別の事なんですね。(この調査結果は、Firefoxの初期状態が普通の人にそれなりに使いやすい形になっている事の顕れと言えるとも思います。)

僕自身は、ペンタブレット(ペン型の入力装置を使って、ペンで字や絵を描くのと同じ感覚で入力を行えるデバイス)を使う時に、指に当たって痛いなーと思ったらペンの軸に何か巻いてみたりプロテクターのような物を作って付けてみたりと、DIYで「カスタマイズ」して使っています。漫画家の人の中には、ペンの軸が長すぎるからとノコギリでぶった切って使っている人もいるそうです。

でも、そういう風にしない人もいるんですよね。使いやすいと思えるありものの製品を別に探したり、使いにくいから使うのをやめてしまったり。そもそも、自分が使いやすいと思うようにカスタマイズするという発想が無いという人もいるのだと思います。

僕自身、あまり拘りを持っていない分野ではそういう行動を取っている気がします。僕は料理をする事が好きで好きでたまらないという人ではないので、調理器具は買ってきた物をそのまま使っていますし、少々使いにくいと思っても面倒だからそのまま放置しています。カスタマイズしてでも使い続けるかどうかは、「なんでもカスタマイズしたがる性格」の有無以外にも、使いにくさを乗り越えてでもそれを使い続けるに足る動機があるのかどうか、どれだけそれを切実に必要としているのか、という事も影響しているのかもしれません。

そう考えると、カスタマイズ性を高くしておきさえすれば万事オッケーとは言えないのだと思います。僕自身、車や自転車にそれほど強い関心があるわけではないので、「タイヤをこれに替えるともっと快適だよ」と言われても「ふーん、そうなんだ。まあ面倒だから僕はそのまま使い続けますよ。」って思ってしまいますし、そのまま使い続けるのが辛いくらいに合わなければ、カスタマイズを検討する前に他の車や自転車に乗り換えてしまうのではないかと思います。同じように、Webを見る事に対してそれほど切実な動機を持っていない人に「カスタマイズすればもっと使いやすくなるよ」と言っても、「面倒だし別にいいよ」って多分言われてしまうでしょうし、その人が「なんかこれ使いにくい」って言ってる時に「カスタマイズすれば解消できるよ」と言っても、「自分で手を入れなきゃ使いやすくならないの? そうなんだったらもう最初から使わないでいいや……もっと別の物を探すよ」と言われてしまうと思います。

ほとんどの「ユーザ」はそういう物だ、と僕は考えるようにしています。だからこそ、デフォルト設定を使いやすくした方がいいとか、初見で使えるようにした方がいいとか、そういう事を言ってるんですね。

ブラウザのアドオン、である理由

今プログラマ的にアツい分野というとHTML5とかWebサービスとかクラウドとかっていう話になると思うんですが、僕がWeb開発じゃなくブラウザのアドオンの開発をやり続けてる理由は、インターフェースとして、より人に近い部分で動く物を作れるからなんだと思います。

ユーザの何気ない無意識での入力をトリガーにして適切な次の処理をサジェストするというのは、普通のWebページやWebアプリの枠を超えた部分の話です。サジェストされる選択肢の1つとしてWebサービスに誘導するのはもちろんアリだと思いますが、起点になるのは特定のWebサービスの画面ではなくて、ブラウザのUIだったりスマートフォンのホーム画面だったりという、もっとユーザに近い部分になるはずです。

そこの所への関心が強いから、僕はWebアプリよりもアドオンを作るのが好きなんでしょうね。

Page 4/243: « 1 2 3 4 5 6 7 8 »

Powered by blosxom 2.0 + starter kit
Home

カテゴリ一覧

過去の記事

1999.2~2005.8

最近のつぶやき