2016年2月9日
アプリケーションの設定はごめんだ! : アプリケーションのユーザビリティを考える
(2016-01-09)by Quil
本記事は、原著者の許諾のもとに翻訳・掲載しております。
(訳注:2016/3/2、頂いたフィードバックをもとに記事を修正いたしました。)
注
このブログ投稿は不満をぶちまけています。かなりのものです。自説は曲げません。長いです。そして、頭に血が上っています。かなり暴言です。
目次
最近、ソフトウェア開発において復活しつつあるとても 興味深い 傾向があるようです。おそらくNode.jsの哲学に影響を受けているのでしょう。何かを使うためには、まず大量の「依存パッケージ」をインストールする必要があり、さらにそのコンフィギュレーションに10時間を費やし、あなたが信じている神(もしくは天の存在)のようなもの―たとえ信じていなくても―に祈ります。そして、とても運が良ければ、また夜空に星がきちんと並べば、画面に”Hello, world”という出力を見ることができるのです。
例えば WebPack や Babel.jsのバージョン6 といった、新しい人気のツールからも明らかなように、どうやら、より多くのコンフィギュレーションが、常により良いということを意味するようです。このことにより、昔Javaがどうしてそれほどまでに人気のプラットフォームであったかについても説明がつきます。
仮説
ツールの人気は、ユーザが浪費する時間に比例する。
アプリケーションの中身は?
なぜプログラミングツールにすっかり嫌気がさすのか(つまり、そうですね、ほとんどのアプリケーションに、間違いなく ^(1) )についてかなり科学的に分析を始める前に、いくつかの用語を確認しておきましょう。
-
ライブラリ とは、ある特定の問題に対する、普通は手を加えられる解決策。ライブラリは 物事を処理 し、私たちはその処理方法の設定ができます。ライブラリを組み合わせることで、より 多くの物事 を処理することもできます。もちろん、設定したり、プログラミングしたり、物事を結合したりする対価は払います。しかしライブラリはこの3つの作業の完了を助けてはくれません。
-
フレームワーク とは、ある特定の問題に対する、手を加えられない解決策。フレームワークは、その作成者が解決しようとする特定の問題に対して、事足りると思う、 非常に特殊な方法 で処理を行います。フレームワークは結合も設定もできません。フレームワークに対してあなたができることは、その上に追加でプログラミングができるだけです。フレームワークはその上に追加でプログラミングするときほとんど何の手助けもしてくれません。誰かがすでにやった何事かを忠実になぞるなら別ですが―それならなぜ、同じことをあなたがやり直すんでしょう?
-
アプリケーション とは、ある特定の問題に対する、手を加えられず、きちんとパッケージ化された、 便利で設定不要 な解決策。アプリケーションは、 ある方法 で処理を行いますが、 その方法は1つだけ です。変更も結合も設定もできません。アプリケーションに追加でプログラミングもできません。アプリケーションはただジョブをやり遂げるだけです。それはオフィスにあるコーヒーメーカーのようなものです。つまり、あなたがボタンを押せば、魔法のように、カップに美味しいコーヒーが現れるのです。
これらの定義があれば、WebPackもBabelも アプリケーション の定義に合わないだけだと結論づけることができます。 フレームワーク の定義にもほとんど合わないので、 ライブラリ というしかありません。
このことは、こういったツールが、「コンパイラ」が文献で定義されたのと同様に「トランスパイラ」を定義し、この2つの言葉は同義ではないと発言したコミュニティから生まれたということを考えれば、驚くべきことではないでしょう。
仮説
プログラマは言葉の定義を知らない
アプリケーションについての考え方が間違っている
タイトルがすべてです。ここはこれで終了です。お読みいただきありがとうございます。
あるいはもう少しお役に立てるかもしれません。ええと…。
アプリケーションは 体験 のようなもの
ちょっとコーヒーメーカーの例に戻りましょう。
コーヒーメーカーは非常に素晴らしいです。「コーヒーを入れる」というボタンが1つだけあります。それを押すと、処理が始まり、コーヒーが注がれます。
あなたは幸せで陽気です。
しかし・・・違ったコーヒーが欲しければどうしますか? コーヒーメーカーのボタンがもっと必要になるかもしれません。砂糖を入れるかどうか選ぶボタンや、コーヒーに加えるミルクの量を選ぶボタン、クリームを入れるかどうかを選ぶボタン、さらには、コーヒーではなく 紅茶 を入れるボタン。もしくは・・・
飲み物が欲しいだけなのに、ここまでくるとあまりにも多くの選択を迫られ、自分でコーヒーを入れるのと同じくらい面倒に感じます。それに加え、コーヒーメーカーの 取扱説明書 も必要です。
悲しみと欲求不満がなぜか対応できないぐらいあふれます。
この2つのコーヒーメーカーの使用体験を比べると、本当に欲しい種類のコーヒーが飲めなかったとしても、 前者の方がずっと良いです。
仮説
人間は選択が苦手で、できれば避けようとする。
これが常識だったとしても、コンピュータアプリケーションは後者を好みます。Babel v5とBabel v6で使用感を比べてみましょう。
これがBabel v5です。
Babel v5 では何とか動いています。
そして、これがBabel v6です。
こ、これはどういうことなのでしょう?
ご覧のとおり、Babel v6はまったく動かないだけでなく、意味不明なエラーが出ていて、問題解決にはどうすべきなのか見当もつきません。
仮説
プログラマは問題解決についてのアドバイスの方法を知らない。
あなたならどうしますか? まあ、動くべきものが動かない理由をインターネットで調べるでしょう。それに時間を費やします。ドキュメンテーションの”’—-help”’コマンドの項目には”'”Usage: babel [options] “”’とだけ書いてあるでしょう。
ドキュメンテーションを読むと気付きます。”’npm install babel-cli”’を実行してES6からES5へのコンパイラをインストールすれば良かったはずだったのに、コンパイラを動かすためには 実際 にそのコンパイラをインストールしなければならないと書いてあるのです。
注釈:
- 2 インストール
以下のコマンドをローカルで実行してBabel CLIをインストールすることができます。
”’$ npm install –-save-dev babel-cli”’
- 3 使用方法
”’$ ./node_modules/.bin/babel src –d lib”’
注
Babel Pre-6.xは、デフォルトで特定の変換が可能です。しかし、Babel 6.xでは変換が標準装備ではありません。明確にどの変換を実行するのか指定する必要があります。その最も簡単な方法は、ES2015 Presetのようなプリセットを使用することです。
言葉がありません。
仮説
プログラマは理屈が苦手です。
そのため、上記の注にある2つのリンク先(1つは問題解決法にはまったく触れていません。余計に混乱し欲求不満となるだけです)を読むと、アロー関数や配列展開をコンパイルするだけに200MBものデータ ^(2) をインストールし、自分の環境で動くようにするのです。どこに保存するのか、どのフォーマットなのか、どうやって使うのかわからないテキストファイルも作成する必要があります。わからないのは、リンク先のどこにも(ドキュメンテーションのどのページにも)何の説明もないからです。
「神様がグチをこぼすことを許さないので、これを”そんなものだ”と受け入れなければならない」とうのは言いましたっけ? そう、良かった。
うまくいっているようですが、そんなこと誰がわかるでしょう。
では、良い考えと思われたこれまでのBabelの方法の何が悪かったのでしょうか? ええ、特に何も悪くありません。選択肢を減らしたければ、プログラムを設定する方法を簡単に追加できたはずです。しかし、そうではなく、 すべてのユーザ に最初にBabelをインストールするという選択をさせることにしたのです。
この問題の解決策
どうやったら、イライラしない、また、ユーザがコンピュータのことを知らなくても済むようなアプリケーションを作成できるのでしょうか。それには、 Elementary OSのヒューマンインターフェースガイドライン から始めるといいでしょう。たとえElementary OSアプリケーションを設計しない場合でも、ガイドラインに書かれていることを全てまねすれば、たいてい、 人間にとって本当に使いやすい アプリケーションが作成できます。
『ヒューマンコンピュータインターフェース』の ヒューマン は強調してもしきれません。設計する際は、使用する人間のことを、ぜひ考えてください。
仮説
プログラマは、HCI(ヒューマンコンピュータインタラクション)テストにロボットを採用している。
(少なくとも自分たちが作ったものが使えるかどうかテストしますよね)
1. 設定より規約
理想的なアプリケーションは、インストールすればすぐに使えるものです。コンフィギュレーションは、一切必要ありません。時間を無駄にすることもありません。しかし、たまに、アプリケーションを起動して実行するには、特定のデータが必要になることがあります。では、あなたならどうしますか。
ルール1:コンフィギュレーションが必要なアプリケーションは間違っている
「ユーザに情報を入力させるのですか?」
それは、 やってはいけないこと です。その情報は既にあるはずです。
-
「ユーザに問題点リストを提供するために、ユーザのGitHubリポジトリ情報が必要です」——Gitなどのバージョン管理システムから解析すること(その情報は既に
package.json
の中にある)。 -
「連携するために、ユーザ名が必要です」——その情報はOSから取得すること。
-
「依存ライブラリが置かれているディレクトリ情報が必要です」——規約を考え出すこと。Node.jsの
node_modules
がよくできているので、それを使うこと。 -
「.xyzファイルを開くためのツールを指定する必要があります」——拡張子と外部ツールを関連付け、
.xyz
ファイルを開く時はいつもそのツールをダウンロードしてインストールすることを勧めること。 -
「そうは言っても…」——必要な情報は、 ユーザ以外から 取得すること。
しかし、時には、コンピュータのどこにもない情報があります。 「そういう場合は、ユーザに尋ねるしかないのでしょうか」——それは、時と場合によります。 アプリケーションを実行するために 、ユーザに情報を入力させることが本当に必要なのでしょうか。もしそうなら、それは、たぶん間違いです。代わりに、アプリケーションを実行するために必要なものをすべてパッケージ化してみてください。
「それでも、いつか必ずコンフィギュレーション プロファイル が必要になります」——確かに。では、コンフィギュレーションがどうしても必要になった 場合は 、ユーザにコンフィギュレーションツールを提供してください。ユーザのユースケースに最適な設定の仕方も手引きしてください。ただし、コンフィギュレーションファイルは使用しないでください。ユーザに手動でコンフィギュレーションファイルを編集させるようなことはしないでください。
2. アプリケーションを使いながらユーザを丁寧に導く
理想的には、アプリケーションは実行しただけでうまく動作すべきです。しかし、時には、それがどうしても不可能な場合があります。例えば、 nvm
アプリケーションを考えてみましょう。これは、Node.jsのバージョンを管理するためのツールですが、バージョン情報を与えなければ、どうやって使用するバージョンを認識するのでしょうか。
ルール2:本当にコンフィギュレーションが必要なら、アプリケーションを使いながらユーザを丁寧に導く
コマンドラインから nvm
を入力すると、膨大な量の情報が表示されます。
情報がとても多すぎます。しかも、1画面に収まりきれていません。
さらに悪いことに、このテキストは、アプリケーションの使い方については、何も説明していません。しかし、この中に nvm use <version>
というコマンドがあります。これが、探しているコマンドですね。Node.jsの特定のバージョンを使用したいのなら、このコマンドを試すことになります。
使い方がわかりません。
「バージョン5.0はまだインストールされていません」と表示されました。これでは、不親切で、どうしたらいいのかわかりません。「問題がある」と言われたので、もっと具体的な情報が表示されるのを待ちます。「問題なのはわかったから、どうしたらいいのか教えてくれ」と叫び返しても、何も起きません。では、どうしますか。 さらに テキストを読んでみます。
もう一度、最初のコマンドを見てみると、リスト内に nvm install <version>
というのがあるようです。少なくとも、上述した暗号のようなエラーメッセージと合っているように見えます。 おそらく 何か関係があるのでしょう。コマンドからは、どの順番で実行するべきかを知ることはできません(どちらにしても全てを実行する必要があるのに、どうしてステップごとに分ける必要があるのでしょうか)。
「では早速、試してみましょう」
あとは、 install
を実行すればいいということでしょうか。
アプリケーションに、同じ動作をする2つのコマンドがあるのはなぜかと考えてしまうでしょう。しかも2つあるうちの1つしか動きません。たとえ、この事実をよしとしていなくても、物事はそうなっています(少なくとも見た目の上では)。
また、別のアプリケーションを実行するためには新しいシェルを開きます。当然ですが、そのアプリケーションもNode.jsのバージョンに左右されます。
数秒前までうまく動いていたのに…。
何が起きているのか理解できず、ぼうぜんとスクリーンを見つめてしまうでしょう。うまく動いていたNode.jsが動かなくなりました。もしかしたらnvmの不具合で、ランダムに問題が起きるのかもしれません。 node --version
を別のシェルで試すと、驚くことに期待通りの v5.0.0
となりました。「では、シェルを開く時は すべての シェルで、 nvm install <version>
を実行するべきなのでしょうか」
もう一度 nvm install <version>
を実行して、その説を検証してみましょう。
うまくいきました。どうしてでしょう?
あまりの驚きで絶句してしまいます。何かをコンピュータ上で使うために、こんなに苦労するなんて考えたこともないでしょう。先ほどBabelを使ったことが頭によみがえり、深いため息とともに、「 おそらく 、そういうものなんだろう」と思ってしまいます。
しかし、他にも方法は あるはず ですよね。毎回、 nvm install <version>
を実行しなくてもいいはずです(知らないでしょうが、実際に nvm run <version>
を実行しても 皆さんのために 働いているようには見えません)。
もう一度、最初のコマンドラインを見てください。毎回、この処理をしなくて済むようにするヒントを探しましょう。 nvm alias default <version>
が目に留まります。そして、そこに”default. node. shell”と書かれています。まるでキーワードみたいですね。これを試してみましょう。
どうして、これが全部必要なのでしょう?
「やっと、うまくいった」と怒りとともに叫びたくなります。肩の重荷はほとんどなくなったでしょう。しかし、なかなかここまでたどり着かなかったコンピュータに、相当イライラしているはずです。「ようやく次に進んで、仕事を終わらせることができる」と、不満を漏らしつつ考えるでしょう。
もっと別のやり方はなかったのでしょうか。もちろんあります。前述したものとは別の、ありえそうな人間とnvmの間のインタラクションを見てみましょう。nvmの目的が、Node.jsのバージョン管理であると仮定します。この目的を念頭に置いて考えてみると、nvmはアプリケーションの新しいユーザ(及びに長期的に利用しているユーザ)にとって、非常に一般的なユースケースを辿っています。
- ユーザは、異なるNode.jsのバージョンをインストールして設定するために、
nvm
アプリケーションをダウンロードする。 - ユーザーはデフォルトのnodeのバージョンを設定できることに関心がある。なんといってもnvmはそれを管理するためのものだから。
- ユーザーはnodeをできるだけ短いコマンドで実行できることに関心がある。nodeと記述するだけで実行できるのが理想的である。
ユーザが、 nvm
を実行すると、アプリケーションは自身がまだ何もできないと気づき、いくつかの一般的な対処法を提案します。
何をするべきかをユーザに知らせると、より使いやすくなります。
ユーザは、nvmを動かすにはまだ設定が必要であると気づきます。インタラクティブなスクリーンでは、迅速に設定するために stable
バージョンをインストールするよう、アプリケーションが提案します(これは、よいデフォルトのコンフィギュレーションです)。設定する必要があるものの、これは大幅な改良です。少なくとも動かすために必要なことを 知らせてくれます。
1つのコマンドですべてが間に合います。
おっと、あなたは use
を実行する前に、どのバージョンのNode.jsもインストールしていませんでしたね。しかしこのコマンドはそれを認識し、適したバージョンをインストールしてくれます。 賢明なのはこれだけです 。そこで できる ことは他にはありません。
簡潔な注意書き
あなたのアプリケーションにエラーがあり、それを修正する方法が1つしかないのなら、 修正しましょう。
インストール後、たった今インストールしたバージョンをデフォルトのNode.jsにしたいか尋ねられます。あなたが望めば好きな時に変更することができると、律儀に示します。 npm use <version>
は一般的に実行されるべきもので、アプリケーションの肝心な部分です。このことを考えると、仕事を減らすための選択肢を与えることは賢明だと言えます。
「で、でも、全てのプログラムで適用されるわけじゃないですよね? プログラム言語の実装のためには、どのようにやればいいのでしょうか?」とアプリケーションの開発者は叫びます。では、 AmberのSmalltalk の例を見てみましょう。
注釈:Stef教授と一緒に、Smalltalkを学びましょう
皆さん、5分お時間をいただけますか?私Stef教授は、皆さんにSmalltalkをお教えしたいのです。約束します。すぐに終わりますよ。
プログラミング言語を学ぶための対話方式のチュートリアルは、実にいいアイデアです
3. 失敗は起こる。その直し方を知りたい
あなたのアプリケーションが予想外の動きをした時、一番いい対処方法は、ユーザのために修正し、ユーザが望む方向に進むことです。もしも賢明な方法で問題を解決できるのなら、ですが。しかしこれは、いつでも可能というわけにはいきません。
ルールその3:もしもうまくいかなかったら、できる限りよい方法で、ユーザがその問題を解決するのを助ける必要がある
次の例を考えてみましょう。
V8には、かつて見た中で最悪とも言えるエラーメッセージがあります。
JSON.parse()
は言っています。「申し訳ありません。ここに b
があるので構文解析はできません」。 b
が一体どこにあるんですって? 本当は何があるはずなの? このコードには b
が2個あることに気付いてる? 間違っているのはどっち? それとも両方とも間違ってる? どうやって直せばいいのよ?
V8のエラーメッセージを見て分かるように、多少は改善されたにも関わらず、大部分は役に立たないままです。特にこれは、JSONのパーサにもう少し手を加えれば、ユーザに非常に役立つメッセージを与えることができる例なのです。
パーサに簡単な変更を少し加えれば、このようになります。
このエラーメッセージは、 何が 間違っているかを理解する助けになるだけでなく、直し方まで教えてくれます。何かを直す方法をユーザに教えてくれるのは理想的ですが、いつも可能とは限りません。しかし、少なくともユーザに何が間違っているかを伝える努力をしなくてはいけません。それは「ごめんなさい、デイブ。私にはできません」と叫ぶのではなく、ユーザが理解できるような形で伝えるべきです。
使えるエラーメッセージなら、少なくとも静的なコンパイラについて言えば、 Elm には この話題に関する非常にいいブログ記事 があります。
恥ずかしながら、上の画像はElmのブログ記事から拝借しました。
4. ドキュメンテーションについて考えるのは、やめよう
ドキュメンテーションは、ライブラリやフレームワークにとっては良いものです。しかしアプリケーションにとっては 最悪 です。もしあなたのアプリケーションがドキュメンテーションを本当に必要としていると考えているなら、複雑すぎますし、ユーザにフラストレーションを感じさせるでしょう。
これは本当です。 XKCD に出ているからです。
注釈:
SOLVE PROBLEMS 問題を解決する
CREATE PROBLEM 問題を発生させる
TOOLS THAT DON’T NEED A MANUAL マニュアルを必要としないツール
TOOLS THAT NEED A MANUAL マニュアルを必要とするツール
TOOLS THAT NEED A MANUAL BUT DON’T HAVE ONE マニュアルを必要とするが、そのマニュアルを持っていないツール
TOOLS WHOSE MANUAL STARTS WITH “HOW TO READ THIS MANUAL” マニュアルが「このマニュアルを読む方法」から始まっているツール
私の意見はご覧のとおりです
ドキュメンテーションの代わりに、単に起動することによってアプリケーションに仕事をさせましょう。環境設定もなし、まったく何もなしです。ユーザに仕事を終えさせましょう。
ルール4:製品を使う前にマニュアルを読むよう、ユーザに要求してはいけない
Appleは理解しています。あなたはただ真似すればいいのです。
Mac vs PC Commercial – Out of the Box
まとめ
コンピュータは最低です。
アプリケーションも最低です。
私たちは、この2つをもっとよくすることができます。
しかし皆さんはやってみようとすら思わないでしょう。
(私もこれに関しては罪悪感があります。)
参考文献
あなたが使えるソフトウェア
Glyph
JavaScriptの疲弊
Eric Clemmons
プログラミングの未来
Bret Victor
全く新しい世界
Gary Berhardt
セルフとセルフ:疑問と理由
David Ungar
株式会社リクルート プロダクト統括本部 プロダクト開発統括室 グループマネジャー 株式会社ニジボックス デベロップメント室 室長 Node.js 日本ユーザーグループ代表
- Twitter: @yosuke_furukawa
- Github: yosuke-furukawa