Sightこの広告は、90日以上更新していないブログに表示しています。2014-03-06APIのバージョニングは限局分岐でやるのが良いちょっと前にTwitterでAPIのバージョニングをどうやるかみたいな話をしていたのですが、そのへんもやもやしているので少し整理しておきたいなと。APIのURLを/api/v1/*とかってやるの、やめたほうがいいとおもうんだけどなぁ。いざv2を作るとなったときに、大量のコピペが発生して後悔するよ、って伝えたい。2014さて、これについて色々と異論・反論も含めた意見が出たのですが、まずは、大昔にURL方式(=コントローラ分割)でやってきて後悔したぼくが、(5年ぐらい前から)現在はどうやってAPIのバージョンを管理しているか?について紹介します。基本原理としては、コピペが多発する根っこで分岐(=コントローラ分割)じゃなくて、必要最小限のところで限局的に分岐するのがいい、という考え方に基づきます。versionを渡し、それをリクエスト単位でスレッドローカル変数に保存し、必要に応じて分岐する」というやり方です。versionの渡し方としては、おおまかに二種類あります。ログインしてセッションを生成する段階でパラメータとして渡す方法。versionが適用されるので、クライアント側からはapi_versionのような付帯情報を毎回送る必要がなく、session_tokenだけをキーとして送ればよくなります。このやり方は、グループチャットのLingrや対戦ゲームインフラのPankiaのような、オンライン・オフライン状態の識別がクリティカルなサービスの場合に有効です。Headerにapi_versionを埋め込む方法です。1このやり方は、データベースのリモートバックアップサービスDumperで採用していますが、毎回送るべき情報が少なく、オンライン・オフラインの区別がほとんどないサービスに有効です。OAuthベースのシステムとも親和性が高いでしょう。versionがリクエストにのってサーバに受け渡されたとして、それを使って分岐する可能性のある場所は、コントローラに限りません。versionを参照する必要がでてきます。versionにアクセスできるようにします。具体的にRailsのコードで見ていきましょう。「APIというコンテキスト」を扱うオブジェクトを定義します。1のような形でアサインすると、自動でスレッドローカルに保存してくれるようにします。以下のコードをlib/api_context.rbに置きます。request.headers['x-api-version'].to_iのような形でアサインします。}endのように局所的に分岐できるようになります。ところで余談ですが、スレッドローカル変数はいわゆる(スレッドセーフな)グローバル変数なので、条件反射的に「使うべきではない」という反応をする人たちがいます。Rails本体でも、たとえばi18nでリクエストごとの言語ロケールをセットするところなどはスレッドローカルで実装されており、リクエストをライフサイクルとする広域変数にスレッドローカル変数を使うのはむしろ定番です。当然ながら副作用としてスコープリークが発生し、MVCの分離が甘くなるので、ApiContextの使用は必要最小限にとどめ、テストの記述にも注意が必要です。議論さて、ここまでの実装をふまえて、個々に議論していきたいと思います。ああ、そういうことか。変わらない限りv2は使わないよね。コピペレベルじゃないときにv2を使うイメージ。2014まさしくその通り!つまり、コントローラ分割だと、よほど根本的で大きな変更がないかぎり、v2を導入することができなくなります。言い換えると、99.9%のサービスでは、v2を導入する日は永遠にやってきません。versionを使って、APIの質をどんどん改善していくことです。非互換な変更を入れなければいけないときというのは、よっぽど慎重にデザインしていても、やっぱり発生します。いうときに、互換性を壊さないために「改善しない」という選択をするのではなく、「古いクライアントはそのまま動く、新しいクライアントではより良く動く、時間とともに良いクライアントが増える、いつかは古いバージョンをディスコン」というオペレーションです。2014これもわかります。いうか、その昔にぼくがURLで丸ごと切り替えるという判断をした理由もこれでした。コードは一行でもいじると壊れる可能性があるので、互換性を最大限に維持したいなら、一切いじらなくてすむのが一番。古いコードはさわらず、新しくv2として書き始める。考えたのですが、これには大きな罠があります。それは、アプリが進化する限り、下回りで依存しているライブラリ(Rails本体、Gemなど)もアップデートし続ける必要があり、それにあわせて結局v1のコードも書き換え続ける必要がある、ということです。v3と増えるごとに、書き換える対象が増え続ける、これぞまさしく「コピペが増える」という表現で伝えたかったことです。これは結局、シングルソースの限局分岐をメンテするよりも多大な労力がかかるので、結果的に後方互換性を壊してしまうリスクは同等かそれ以上にある、ということになります。それだったらば、ライブラリにあわせての変更は一箇所で済み、分岐が限局されているやり方のほうが、結果的に品質も高くなるのではないか、という考え方もあるかなと思います。層でバージョンニングを意識しないといけませんしね。2014そうそう、極めつけはこれだと思います。コントローラを分けても、モデル層やJSON生成層その他で発生した非互換な変更には無力なので、結局ぼくがやってるのと似たような仕組みでMVCを超えたバージョンの受け渡しが必要になります。コントローラだけを大局分岐してバージョン管理できた気になるというのは、やはり悪手だろうと思います。versionin)を設けるという方向にシフトしようとしている。2014なんかすごそうなことをやってる。kwsk!というわけで、33の続報をRebuildできけることに期待。ぼくなりの現時点でのテンポラリな結論としては以上なのですが、MVCがリークしているのでテストの書き方が難しいとか、まだまだ満足のいく水準にあるとはいえず、これという正解が見つかってない世界だと思います。このやり方でうまくいってるという方法があれば、ぜひ教えてください。comment2014-03-06ユーザとユーザを多対多で関連付けるモデルを共通化する思いのほか前回のRailsプチ・デザインパターンの紹介に反応があったので、こういう小ネタも出していったほうがいいのかな、ということで第二弾。ソーシャル系アプリだと、ユーザとユーザを関連付ける多対多のモデルがたくさんでてきます。一般的なところではフォローとかブロックとか足あととか。admirer(こっそりlikeするけど両思いだったらおめでとうって通知がくるってやつ)だったり、いろいろなモデルがこのパターンにあてはまります。この場合、「AがBをフォローしている」「BがAをフォローしている」「AとBがお互いにフォローしている」という3つの状態があるわけですが、相互フォローの状態は「AがBをフォローし、かつBがAをフォローしている」と読み替えてSQLでも記述可能なので、以下ではシンプルに単方向のグラフで全てを扱うものとします。することで、フレンドリクエストとそれへの承認というのも、同じ枠組みで扱えるようになります。一般的にはこういう感じの記述になるでしょう。:throughも定義したくなるかもしれませんが、user.follows.preload(:target_user).map(&:target_user)などとすればFollowモデルの向こう側にいるユーザ一覧も簡単にとれるので、あえて定義しないことにします。followsテーブルの構造はこんな感じ。target_user_id)の組み合わせにユニーク制約つきのインデックスをはると同時に、target_user_id単独のインデックスもはります。target_user_id)のインデックスが使えるけれども、target_user_id側から検索する場合にはそれが使えないので、単独のインデックスを用意してやります。あるユーザを削除するときには、関連するfollowsレコードを、まずuser_id側から探して消し、またtarget_user_id側からも探して消してやる必要があります。:delete_allを定義して、ユーザと一緒にカスケード削除されるようにします。'target_user_id'さて、ここでBlockやVisitやWinkといったFollowにそっくりなモデルが増えてくると、User側のコードは上記のコピペでどんどん膨れ上がっていきます。4から正式な機能へと格上げされたActiveSupport::ConcernでDRYにすることを検討してみましょう。endendをapp/models/concerns/graphical_belongs_to.rbに保存します。上記の準備ができれば、モデルは以下のように書き換えられます。GraphicalBelongsToendさて、ここでいったん一区切りとし、冒頭に少し触れた「相互フォロー状態はSQLで記述可能」という部分にたちもどってみましょう。アイデアとしては、「AがBをフォローし、かつBがAをフォローしている」というAND集合を取り出せばよいので、followsテーブルをセルフジョインしてやるのがよさそうです。}というスコープをFollowクラスに定義してやれば、user.follows.reciprocalで相互フォローしているユーザ一覧がとれるようになります。これではテーブル名が固定になってしまうので、汎用化することができません。Rails標準の機能ではジョイン時にテーブルエイリアスを指定することができない(これができるようになるだけで数々の問題が解決するのですが。)ので、ジョインの記述を生のArelを使って組み立てることにし、reciprocalメソッドとしてGraphicalBelongsToに追加します。endendちょっと煩雑に見えますが、やってることは基本的に文字列のベタ書きと同じで、違いは、どのクラスでも動くということです。こんな感じで、モデル間で共通する処理はどんどんくくりだしていくことができます。このアプローチの何がいいかというと、共通部分を奥にしまいこんで隠せることで、各モデルに固有の処理をする部分がよりハイライトされる・それに専念できるということです。ユーザの持ち物を扱うメソッドがUserに集中しすぎて、Userクラスが肥大化してしまうというのはよくあることですが、せっかくFollowやBlockといったクラスがあるのだから、各モデル固有の処理はそちら側に書いてやるほうがコンテキストに沿った分離がしやすいはずです。そのために、has_manyにはextendというオプションがあり、外部モジュールを取り込むことができます。これをうまく使ってやることで、拡張をUserクラスに直接書かずに済みます。いうわけで、GraphicalHasManyを拡張して、オプションをとるようにしましょう。endendそして、モデルにはこう書きます。endendこうすることで、user.follows.since(3.days.ago)のようなFollowの拡張を、Followクラス自身に書いていくことが可能となり、Userクラスはスッキリしたまま、将来的にも変更がいらない状態になりました。Afterでコードを見比べてみると、その違いを体感できるでしょう。Inheritanceを使って実現する方法もあって、そちらのほうがコード自体はシンプルになるのですが、多対多のテーブルはそれ自体がユーザ数の二乗で増えていくのに加えて、複数のモデルが同一テーブルに同居することにより、レコードの増加スピードはさらに加速されるのでボトルネックになりやすく、最初からテーブルを分けておくのが得策です。}のようなデフォルトスコープを使って論理削除を実現している場合にも対応するため、GraphicalHasManyやGraphicalBelongsToをもう一段深く拡張していくこともできるのですが、だいぶ話が長くなったので今回はここまで。それにしても、ORMもここまで来ると次元が違いますね。生SQLの時代には戻れない。comment2014-03-05プライマリキーを使った1:1関連でカラム数の多いテーブルを分割するおそらく多くのソーシャル系アプリにあてはまるRailsのプチ・デザインパターン的な話。カラム数にしてざっと25個。これを、全部ひとつのusersテーブルに詰め込むのは、コードの見通しという観点からも性能の観点からも、あまりよろしくありません。ユーザ関連の情報を扱う局面としては主にメールアドレスとパスワードなどを使ってログインする(アカウント情報)プロフィール情報で条件を指定してユーザを検索・推薦する(プロフィール情報)という2つの独立性の高いユースケースにわかれるため、ログイン処理をやってるときにはプロフィール情報はいらないし、プロフィールを検索してるときにはメールアドレスやパスワードをロードするのは無駄です。開発やデバッグ時に関心のない情報が大量についてくるのは純粋に邪魔です。そこで、このテーブルをusersとprofilesという2つのテーブルに分割することを考えます。:userendとしておいて、profilesテーブルにuser_idカラムを作って参照してやるのがrails的には普通だと思います。!よく考えてみると、usersとprofilesは完全に1:1の関連であり、あたかも同一のテーブルをたまたまカラムのグループで2つに分割しただけの存在です。すると、プライマリキーさえ一致していれば、わざわざuser_idという外部キーを作ってやる必要はないはずです。そこで、以下のようなパターンを使います。'id'endこれだけで、usersとprofilesのプライマリキーが完全に一致するようになり、自分のidを使って相手を探しに行くようになります。余計な外部キーがいらなくなるので、インデックスも不要です。あらゆる点で無駄がなく、すごくスッキリしますね。UserとProfileの両方にまたがる検索条件をつけての探索も、ActiveRecordのパワフルなスコーピングを使えば、まったく問題ありません。以下のようにjoinsとmergeメソッドを組み合わせたスコープを定義してやることで、User側に定義したスコープをProfile側からも使えるようになります。'active'この考え方を応用すると、1:1でのテーブル分割が割と気軽にできるようになり、可能性が広がってきます。3.2から導入されたActiveRecord::Storeという、text型のカラムにyamlやjsonなどの塊を突っ込んでKVS的に使うという機能があるのですが、usersテーブルに直接このカラムを追加すると、User.findするたびにこのカラムの中身まで全部読むことになり、非常に無駄です。そのyamlやjsonの深い部分で変更があったかどうかをトラッキングする方法がないため、レコードの更新処理があるたびにyamlやjsonの全体を再ダンプして比較する検出処理が走ります。これは、textのサイズが大きくなってくると無視できないコストです。ActiveRecord::Storeは、そもそもカラムに昇格させるほどではない「あまり重要ではないが参考のためにとっておく」程度の情報をまとめて突っ込んでおくための入れ物なので、普段は必要ないことのほうが多いでしょう。すると、このカラムだけを分離した別テーブルにすることも考えられます。:dataendさらには、DeNAのソーシャルゲームのためのMySQL入門その2で挙げられているテクニックですが、ソーシャルゲームなど更新頻度の高い用途の場合、更新パターンに応じたテーブル分割というのも有効です。参照中心のアカウント情報(メールアドレス、パスワード、トークンなど)とは別に、ユーザがログイン中にはひっきりなしに更新されるようなゲームデータ(ヒットポイント、経験値など)は、usersテーブルからは切り離して1行あたり数十バイト程度の小さい単独のテーブルにしておくと、同じページサイズにのる行数が増えるため、(適切なflush設定をしてあれば)更新処理をまとめて実行できる可能性が上がり、より少ないIOPSで大量の処理をさばけるようになります。'id'を使う、というのは、非常に応用範囲の広い考え方なのでオススメです。incrementが連動するので有効です。途中からprofilesテーブルを追加するようなケースや、profiles側を削除→挿入することがあるようなケースでも問題なく動くようにするには、before_createで明示的に親からidのコピーを行っておきます。かみぽわーるのように、idカラムのAUTO_INCREMENTを外しておくと、idが空のまま挿入しようとしたときに例外を投げてくれます。comment2014-01-03テスト考2014年々、ウェブアプリを開発するときにテストを書こうという機運が強くなっていると感じる。これは、開発パラダイムの成熟を意味することであり、基本的に良いことだと思っている。同時に「テスト原理主義」とでもいうような極端な考え方もでてきていて、開発スタイルをめぐって摩擦が起こっている。この議論は「テストは、ないよりあったほうが良いよね」という、微視的には誰も反論できないロジックに押し通されがちで、「地獄への道は善意で舗装されている」の典型的な現象に見えて仕方がない。テストを書かない、というと背景にどんな深い考えがあっても素人くさく聞こえ、逆にテストを書くというだけで良いプログラマーに見える、という非対称な化粧効果がある。ソフトウェア・コンサルティング会社がテスト好きなのは決して偶然ではない。ソフトウェアというのは、結局のところ、動いてナンボ、使われてナンボである。期待するものが作れて動きさえすればどんな言語でもいい、どんなに汚いコードでもいい、という考え方がある。ぼくはその考え方には反対だが、その対局にあるのが「テストカバレッジ100%」ならば、もっと強く反対する。ぼくは会社だけでなく個人でもいくつかのウェブサービスを作ってきているけれど、新しめのプロジェクトではテストはほとんど書かなくなった。それどころか、コメントすらほとんど書かなくなった。それと反比例するように、コード自体のクオリティは、ぐんぐん向上している。思うに、それなりにできるプログラマが一人で作っている場合には、テストやコメントはほとんど必要ないしかしチームで開発する場合には、他人にコードを壊される機会が増えるので自然とテストを書くようになる一人でゼロからリリースまでやりぬいた経験のあるプログラマーは1%もおらず、あとの99%はチーム開発しか経験したことがないだからテストは絶対的なものとして君臨するおおよそ、以上のような流れではないだろうか。ポール・グレアムは、「頭の中にプログラムを入れる」という有名なエッセイで、「コードの同じ部分を複数の人にいじらせない」といった。「複数の人でプロジェクトをやろうと思うなら、それをコンポーネントに分けて、それぞれを一人が受け持つようにすることだ。Requestベースのワークフローというのは、これの真逆をいくもので、同じコードを不特定多数でワッショイワッショイ編集しまくるので、誰にとっても全体像が見えにくくなっていく。組織としては、ある重要なコンポーネントを一人の人間に依存するのは怖いので、それなりのコストを払ってでもリスクヘッジしたい。「組織というものを定義付ける資質の一つは、個々人を交換可能なパーツとして扱うということだ。」と上記のエッセイに書かれている通りのことだ。テストやコメントは、「個々人を交換可能なパーツとして扱う」ための必要悪なのであって、保険みたいなものだ。テストはリファクタリングを助ける?邪魔する?良いコードを維持するためには内部構造をしょっちゅうリファクタリングする必要がある。テストの存在は、外部インターフェースを壊すことなく内部をリファクタリングすることを可能にしてくれるが、一番よく変化し、壊れやすいのは内部構造のほうであったりする。こちらは、残念ながらテストで解決するのには向かない領域だ。(とはいえ、そんなことさえ知らず内部構造に対するテストを書いて自分で自分の足を撃ってるプロジェクトが多いことを考えると、もっと事態は深刻かもしれない)もし、あなたのアプリが公開されたAPIをもち、それを維持していく必要があるなら、もっとも特徴的なAPI(たとえば認証まわり)いくつかに対してテストを書くべきだ。すべてのAPIに対してテストを書いてカバレッジ100%を目指すのはやめたほうがよい。追加で書かれるテストの存在価値は限りなくゼロに近いし、そうでなければ、そのことのほうが問題だ。その追加で書かれるテストは、おそらくほとんどが他のAPIからのコピペになるだろう。コピペでコードを書くことは害悪とされているのに、テストならばコピペは許されるのだろうか。よいコードは、何も書かないことである。いうと禅問答のようだが、自分で車輪の再発明をするのではなく枯れたライブラリを使うというのも、この範疇である。これは、同じことを実現するコードなら短いほうがよい、と一般化できる。した場合に、テストコードというのは実現したいこと(=アプリケーションコードの価値)には影響しないが、書いた行数は増える、すなわちメンテナンスという意味ではアプリケーションコードと同等のコストを払うことになるので、同じことを実現するためのコード量が増え、冗長になったことと等価である。テストは必ず書くという考え方はばかげている。アプリケーションコードと全く同じで、コストとリターンを見極めながら必要に応じて書く、が正しい。コメントが必要なコードは抽象度が甘いこれは、経験からいうと、コードのクオリティが上がったからコメントが必要なくなった、というほうが正しいかもしれない。Rubyのような自然言語に近い記述ができるパワフルな言語では、コメントに書くぐらいならコードにしてしまったほうが読みやすくなるケースも多い。自然言語で仕様を記述するのにくらべてコードが複雑でコメントが必要になるケースというのは、得てして対象の理解が曖昧で、したがってコードの抽象度が甘いだけのことが多い。これは、実例を出さないとわかりにくいだろうけど、サクッと出せるシンプルな例題が手元にないのでちょっともどかしい。それでも、コメントを書く機会はテストよりは多い。未来の自分は別人なので、過去の自分がどういう経緯で今のような実装にしたのか、書いておいてもらわないと理解できないからだ。いう場合には、悩んで現在のような実装に妥協した理由を、簡潔にコメントとして残しておく。逆に、ダラダラと長くコメントを書く必要があるような甘い実装は許容しないというルールでもある。これは経験上、けっこう良い規律としてワークする。Overflowなどへのリンクをコメントに貼っておく。なければ自分で外部サイトに書く。ソースコード内にはダラダラ書かない。最後になったけど、時代の進歩という意味で、これが一番大きいかもしれない。ウェブアプリならAirbrakeやHoneybadgerのような例外通知機構を導入することで、ユーザが踏んだバグをもれなくリアルタイムに知ることができるようになった。これらのサービスは、同じ種類のバグレポートが何度も通知されないようになっており、影響範囲の大きいバグをデプロイしてしまったときにもメールボックスが溢れてしまうというようなことがない。Errorは、もれなく追跡できている。無料なので、あらゆるプロジェクトで使っている。おかげで、たいていのバグは、デプロイ直後に見つかり、すぐ修正できる。テストなんかより、よっぽど日々の役に立っているという実感がある。いまAirbrakeの履歴をざっとみて、「これ、テストがあれば防げたなぁ」と感じるバグの割合を探ってみると、5-6%程度もない。テストのカバレッジ100%であっても防げなかったバグがほとんどだったということになる。ほとんどの場合は、そもそも想定外の手順でリクエストがきたり、壊れたデータがきたりという例外なので、想定した範囲のケースしか扱えないテストで検出できないのは当たり前である。逆に、こうしてプロダクションにリリースしてから発覚した「想定外の手順」や「想定外のデータ」をレグレッション対策としてテストケースに追加していくのは、ものすごく有効だ。自分の頭で想定できないパターンなので、将来の役に立つ。予測にもとづいてテストケースを増やすのではなく、実際に起きた問題にもとづいてテストケースを増やしていく。これはYAGNI原則という意味で重要なアプローチの違いである。その結果、最近では「エラーゼロ」が個人的な目標になっている。新しく開発を続ける限りバグはゼロにはならないけど、とにかくすぐになおす。慢性的に発生する問題をひとつも放置しない。このゴールを追求すると、プログラミングのレイヤーだけではなく、ミドルウェアやOSやインフラに関する深い知識が必要になるけど、そういったものを学ぶ良いきっかけでもある。ソフトウェアがある程度の規模になると、エラーゼロというのは現実的ではないと思っていたけれど、そんなのは言い訳にすぎないと思うようになった。モダンなエラー通知システムを使ったことがないのにソフトウェア品質を語り、テストの有用性を説くというのは、老害以外の何ものでもない。使ったことのない人は2014年のやることリストに「Airbrakeの導入」を追加しておこう。まとめまとめると、今でもテストを書いてるのは以下のようなケースである。一度発生したレグレッションの再発予防(先回りはしない)複雑なステップを踏む特異的なフォーム(サインアップなど)外部に公開するAPIのうち特徴的なもの(認証や課金など)こう書くと、すごく大量にあるように思えるかもしれないが、実際のボリュームは極めて少ない。おかげでテストのS/N比は高く、実際に役に立つテストになっている。テストには習慣的な側面もあるので、書くのがおっくうにならない程度の周期で書くようにしている。ウェブアプリ開発が1980年代のミドルウェア開発やゲーム開発などと同じ道のりをたどっていくとするならば、この次にくるのは専業のQAチームが開発チームと独立して存在してリリースのサインオフ権限を握り、想定外のパターンをテストしまくってリリース前にバグを出し切る、という体制になるのかもしれない。このアプローチが素晴らしいのは、開発者が自分で想定したテストを書いて満足するというマスターベーション的なテストではなく、本当の意味で想定外のケースがテストできることだ。想像に難くないことだが、開発やリリースのサイクルは劇的に落ちる。成熟というのにはそういう面もあるのだろう。なんにせよ、現在のウェブアプリ開発におけるテストなんて一歩間違えれば「ままごと」みたいなレベルだから、そんなに原理主義的になるのはダサいよねって話です。テストを一行も書かないあなたはクビですので念のため。comment2013-12-30出口が開いてないと腰を据えられないはてなブログ、使いやすいので気楽にいろいろ書きたいのだけど、なぜか本腰で書く気になれない。理想的なブログツールを求めて自分でブログツールを開発してみたり、その途中でGhostを見かけて、やりたいことがほぼ同じだとわかったのでもう自分で作らなくていいやと応援する側に回ってみたり、と右往左往している。そんな風に逡巡してる理由を自分なりに考えてみたんだけど、一言でいうと「ここにはエクスポート機能がないから」に集約される気がしてきた。実際、Ghostのフォーラムでも同じ質問をしている。TwitterやFacebookのようなフローで垂れ流しのサービスなら、あまりそういうのは気にならない。そもそも情報を整理する目的で使ってないし、どちらかというとチャットの延長上でS/N比が低いから、再利用性の高い情報をそこに貯めていこうという動機が、ハナからない。ブログは、ふわふわと浮いているさまざまなアイデアを一本のコンテキストで串刺しにして、ひとつのアーティクルとして編集・整理することができる。その編集という工程に付加価値があるからこそ、いまでもブログは生き残っているし、今後も残り続けるのだと思う。ブログのコンテンツの寿命は平均的なウェブサービスの寿命よりも長い。昔はあまり気にならなかった、データのポータビリティみたいなものが、より大きな比重をもって感じられるようになってきたのだとおもう。どんなに大きな会社の有名なサービスでも、方針転換などによってある日突然なくなったりするということを、ぼくらは何度も何度も目にしてきた。そんな状況で、ある一つの会社の一つのサービスに、魂を込めて書いた自分の人生そのものであるような文書を、唯一無二の保存場所として預けることができるだろうか。研究者が自分の論文をあるウェブサイトに掲載するとして、自分のマシン上に元本がない状態でも安心できるだろうか。そのような制約下で、本当に素晴らしいコンテンツを書き上げようというエネルギーは湧いてくるだろうか。この構図には、変なたとえだが、社員をいろいろなルールで縛ってがんじがらめにして小さくまとまらせておきながら「うちの社員には突き抜けた行動力のある優秀なのがいなくて。」と愚痴をたれる上司に似た矛盾を感じなくもない。現在のネットのトレンドとして、データの寿命を意図的に短く10秒まで縮めたsnapchatのような揮発性のコミュニケーションと、長く残り続けることを志向するブログのような文書志向のツールとの二極化がますます進行していると思う。「長く残り続ける」というのは、ブログのたくさんある特性の一つではなく、進化していくネットにおいて他のツールと差別化していく上で最も重要な特性になってきてるのではないだろうか。サービス提供者の立場からすれば、エクスポート機能を排除してユーザとデータを囲い込みたいというのは順当な心理ではあると思う。その発想はあまりにも「器が小さい」ように思う。実際、フローにすぎないTwitterですらアーカイブのエクスポート機能を提供しているし、Googleに至ってはTakeoutという、エクスポートセンターのような場所さえある。資本主義の権化といわれるアメリカの、それも株式を公開している企業がこのような懐の深さを見せていながら、日本ではカッティング・エッジな存在として知られるはてながセコい囲い込みに終始しているように見えてしまうのは、なんとも残念でならない。ブログというツールが果たす役割を考えるとき、「コンテンツが長く残るという安心感」につながる一つの切り口として、エクスポートというのはむしろこれまで以上に強化していくべき側面ではないだろうか。とってつけたようなエクスポートではなく、たとえば、リンクしたDropboxアカウントにMarkdownファイルを吐き出してくれるとか、逆にDropboxに置いたMarkdownファイルをインポートしてブログ記事化してくれるとか、記事を公開するたびに記事単位でダウンロードリンクが生成されるとか、ブログを真剣に書きたい人の深層心理に刺さるアドバンテージとして積極的に開拓していく余地は大きいように思う。いうわけで、はてながエクスポートを実装するのが先か、Ghostが使えるレベルになるのが先か。2014年にはブログを再開できることを願いたい。Eastはじめます以前から予告していた、新しくはじめるスタートアップの件について、いよいよご紹介します。パートナーは時岡まりこ。オックスフォードのMBAで、ロンドンのスタートアップQuipperの共同創業者兼COOをやってきていた人です。やることは、アメリカやイギリスなど、主に英語圏の欧米諸国に住むアジア人向けのデーティングサイト。アジア諸国は経済の発展がめざましく、人口ボーナスもあって、ますます世界の移民動態における存在感が高まってきています。西欧諸国に住むアジア人は、自分が育った環境と比べて文化的なギャップが大きいので、似たようなバックグラウンドの友人・恋人とまじわる傾向があります。故郷を振り返ることなく現地の人と結婚したりする人もいるのですが、全体の統計レベルでみるとやはり圧倒的に同一民族内での結びつきが多数派です。いろいろな人と付き合ってみたけど、やっぱり最後に結婚する相手を探すとなると、小さな頃に同じようなことを経験し、深いところで価値観を共有できる相手がいい。いう人が周囲に少ない。このような悩みを抱えている人々は意外なほど多く、こうした問題をインターネットの力で解決することには、大きなチャンスがあると考えました。デーティングサイトといえば、日本語にすると「出会い系サイト」ということで、ややダークなイメージが残っているかもしれませんが、ここ米国では世代をこえて完全に一般化していて、Match.comやeHarmonyを使っていることを公言している人も珍しくありません。Mingleなど、バーティカルな市場が立ち上がってきています。そんな市場環境の中で、西欧諸国に移住したアジア人向けという、自分たちの土地勘があるマーケットから攻めていこうというわけです。ぼくは、渡米してからの8年間、いかにもシリコンバレー的な、エンジニア集団でものを作るというスタンスでやってきました。最初は、インフォテリアUSAの立ち上げでアメリカ人のエンジニアチームで消費者向けネットサービスを作り、その次はパンカクで日本にいるエンジニアチームと一緒にモバイルゲーム向けのプラットフォームを作り、という感じで色々やってきて、Cometを世界で初めて実用化したサービスLingrや、3年間で3000万ユーザまで急成長したプラットフォームPankiaなど、技術的な達成は大きかったのですが、それをビジネスに結びつけるところがうまくいきませんでした。これらの経験を通じて、自分は何が得意で、何が苦手か、はっきりと痛感したのです。自分でそうありたいと願っていたほどビジネスのセンスがよくないだとか、マーケティングもからっきしダメだとか、認めたくないけれども認めざるをえない弱点が、長年の失敗の積み重ねで、ようやく見えてきたのです。一方で、エンジニアとしてのセンスやバランス感覚には、今でも確固たる自信を持っているということも。オラクル時代の共通の友人を通じて今回の話を紹介されたときには、すぐにピンときました。トッキーは、冒頭で紹介した経歴からわかるようにビジネスパーソンとして申し分のないキャリアを積んできていて、また実際に話をしていくうちに、事業の難しい局面でも折れることなくやり切ることのできる芯の強さのある人だと感じました。私情を挟むことなく徹底的にロジカルにものごとを考える習慣があり、速いスピードでガンガン意思決定していくという部分ではスタイルが共通していて、しかし片手間では絶対に追いつけないレベルでの専門性を分担するという、理想的なシナジーがあると確信できたのです。何でも自分一人の力でやろうとして、うまくできなくて落ち込んで、というのは士気が下がるだけでなくて、人間としての成長という観点からもタイムロスです。向上心やガッツは誰よりもあると自負しているけれども、気ばかり焦って何をやっても改善しなくて、さらに焦って。いう空回りの悪循環は苦しいものです。Founder」でした。今回は、モノよりもヒトで決めたし、その直感を信じることにしたのです。彼女はロンドン在住で、ぼくはラスベガス。地理的に離れているので、週三回のミーティングはskypeベースです。最終的には、メインのターゲット市場となるニューヨークなどのメトロエリアにHQを構えることになる予定です。開発チームは、イギリス在住のビジュアル・デザイナーのRobと、ブルックリン在住のフロントエンド・デザイナーのScottとぼくの3名、3つのタイムゾーンでガッツリ開発してきており、そろそろベータリリースが見えてくるといった頃合いです。存在価値のあるものをつくりあげたい。East成功のためになら、石にかじりついてでも、つべこべ言わず何でもやるつもりです。comment2013-08-28ラスベガス生活がはじまって7月にラスベガスへ引っ越してきてから、あっという間に2ヶ月近くが経ちました。思いがけず仕事の変化が重なって、忙しすぎてアップデートできなかったのですが、忘れないうちにラスベガス生活について書いておこうと思います。意外に過ごしやすい気候まず最初に、一番心配していた気候について。到着した当初が気温のピークで、華氏113度(摂氏45度)という超絶猛暑だったのですが、結論をいえば「意外と問題ない」。先月に出張で行った東京のほうが蒸し暑くて不快感が強かったです。いうのも、ラスベガスは湿度がほぼゼロの砂漠気候。これだけ気温が高くても、汗ダラダラということがありません。汗かきの人間にとっては、全身が汗だくになって、それが冷房で冷やされるというのが究極の不快感なのですが、そういうことが起きないのです。汗かきでない人にとっての夏というのはこういう感じだったのか、とある意味で新鮮な経験です。陽射しの強さは桁違いですから、自動車の窓に断熱フィルムを取り付けるのは必須です。この処置をしてからは、外出時にも快適に過ごせるようになりました。屋外の駐車場にしばらく停車するとハンドルが握れないぐらい熱くなりますが、これもサンシェードを使うようになってから解決。サンマテオ・サンフランシスコ時代には、どんなに暖かい日でも夜になると冷えるので、Tシャツだけで一日過ごせるということが年中通してほぼなかったのですが、今ではシンプルにTシャツ・短パン・サンダルという軽装がちょうど良いので、いたって快適です。いうか、むしろカリフォルニアこそがこういう気候だと思っていたのですが。アメリカ人がちょっと暑いと感じるぐらいの温度が日本人にとってはちょうどいい、という、エアコン設定温度をめぐる飽くなき戦いはよく知られていますが、その傾向はここでもあてはまりそうです。気持ち良い明け方も素晴らしく、エアコンが必要なのは午後の数時間だけだし(ただし、これは建物全体にエアコンが効いてて外部から熱を取り込むのは窓側の一面のみという高密度なコンドミニアムで、かつ北向きの部屋ゆえかも知れませんが)、年中暖房を入れっぱなしだったサンフランシスコ時代とくらべて、トータルで見れば生活空間の気温に関しては改善されたという印象です。想定外だったのは、夏はモンスーンの季節で、結構雨が降るということ。それも、洪水を引き起こすような激しい雷雨もあります。こんな感じで道路が完全に冠水して、車が流されたりしてました。この夜には大規模な停電も起きて、エレベーターが停止したため、30階以上という高層階にある自分の部屋に戻ることができずロビーで復旧を待つことになり、翌朝は海外出張のフライトなのに準備どうしよう、そもそも飛ぶのかな?などと心細い思いをしたりしました。この他にも、引越し業者が荷物を配達してくる日を勝手に二週間も遅らせたり、やっと届いたと思ったら荷物が半分しかなかったり、家具を買ったらことごとく配送中に壊れてたり部品が足りなかったり、、、というアメリカ生活でありがちな地雷をフルコースで踏んでエネルギーを吸い取られたりもしましたが、悪いことばかりではありません。Charlestonの山火事を目撃したり、いい感じのコワーキングスペースに通い始めたり、こんな感じで色々な出来事を楽しんでいます。忙しくて、まだ「いかにもラスベガス」っていうストリップ界隈に繰り出す機会はぜんぜんないのですが、新しい生活の基盤はようやく整ってきました。ラスベガスに足りないもの逆に、ラスベガスに来てから不便を感じることとしては、ニジヤやミツワのような大手の日系スーパーがないサンフランシスコにあったようなオシャレ系のカフェがほとんどない緑の草木がほとんどない(砂漠なので。小さな日系のスーパーはいくつかあるのですが、やはり品揃えがちょっと物足りないです。本国の勢いを反映してか、韓国系のスーパーは巨大なのがあって、そこに日本製の商品や日本食の食材も置いてあるので何とかなるのですが、かゆいところに手が届かない。和食レストランはサンフランシスコよりレベル高いのですが、どうやって食材調達してるんでしょうかね?ロサンゼルスから取り寄せてるのかな?逆に、この3つさえ我慢できて、あと街中にあるあまり上品とはいえない看板類に慣れてくれば、物価は目に見えて安いし、町の歴史が浅いゆえにいろいろなものがモダンで新しくて便利だし、ポテンシャルの高さを実感できます。今回は勢いでラスベガス移住を決めてしまったので、住み始めてから知ったことですが、ラスベガス西部のサマリン、南東部のヘンダーソンは落ち着いた感じの街で、住民の所得水準や教育水準も高く「全米住みやすい街ランキング」のトップ常連です。いってみればベイエリアでいうクパチーノやフォスターシティみたいな雰囲気で、そういう郊外の選択肢もちゃんとある。住めば都とはよくいったもので、今まで色々なところに住んできましたが、どの街にもそれぞれに良さがあります。最初はなじめなくても、住んでいるうちに大好きになっていく。引っ越す前は、どうしてもネガティブな面ばかりが気になって、これで正しかったのだろうかと選択を疑ったり不安になったりするのですが、エイヤで実行してしまえばたいてい杞憂で、むしろ良い方向に発展する。これ、仕事や結婚など、人生で大きな決断をするときには何にでもあてはまる気がしますね。一度決めたら、とことんポジティブにやりきることが大事。こんな感じで、引き続きラスベガスでの生活をエンジョイしていきたいと思います。そんななか、新しいスタートアップの起業準備のためロンドンに行ってきたりしたのですが、そのあたりについてはまた今度。