IT戦記 このページをアンテナに追加 RSSフィード Twitter

2010-09-29

Skype5 のビデオ会議を試してみた

やっぱり、「誰に話しかけてるか分からない問題」はビデオでは解決できないかあ。

f:id:amachang:20100929230332j:image

ちなみにみんなでゲームを見てます。

2010-09-22

オーマ株式会社に入社しました

はじめに

今日から、オーマ株式会社の二人目の社員として、オーマ株式会社に入社いたしました。(大事なことなので2回言いました)

f:id:amachang:20100922111359j:image

よろしくお願いいたします。

オーマ株式会社では

あのひと検索 SPYSEE [スパイシー] というサイトを作っています。

僕も、これれから SPYSEE の企画、開発、運用、そして、様々なサポート(トイレ掃除とかね!)をやっていこうと思っています。

みなさま、よろしくお願いいたします!

今日は、僕が「この会社で何をやっていきたいのか」を書いておきたいと思います。

これから何をやっていきたいか

f:id:amachang:20100922110912j:image

僕がこれから SPYSEE でやっていきたいことは三つあります。

それは、

  1. 「運命の出会い」の確率をあげたい!
  2. 人の背景を知ることで、コミュニケーションをもっと楽しくすること
  3. アピールが苦手な人(シャイなあんちくしょう)でも損をしない仕組みを作ること

です。

これは、あくまでも「今、僕が考えていること」でこれからまたたくさん出てくるかもしれませんが。

「運命の出会い」の確率をあげること

「運命の出会い」ってしたことってありますか?

たとえば、僕だったら

id:ZIGOROumixi で知り合ったこと

偶然「はてなダイアリー」を使って id:secondlife さんと知り合ったこと

id:yukobaShibuya.JS の帰り道が同じ方向だったこと

サイボウズ・ラボを知り id:nishiohirokazu と同じ会社に入ったこと

などなどたくさんありますが。

こういう、人生を変えるような人との出会いって、今のところかなりの部分が「偶然」に任されているのではないかと思っています><

これをなんとかしたい!

もっと、「たくさんの人のこと」を知れて、そして、「自分のこと」を知れる

そして、「人生を変えるような出会い」を「偶然」じゃなく自分で掴み取れる、そんなサイトを作っていきたいです!

人の背景を知ることで、コミュニケーションを楽しくすること

よく名刺交換をするとき、「何を話そうかな」と名刺の肩書きや会社名から会話を考えるんですけど。

でも、出てこないんですよね(^^;

で、出てきた言葉が

僕「あ〜、この会社知ってます」

相手「ああ、そうですか」

僕「……」

相手「……」

orz

これをなんとかしたい!!

こんなとき、少しでも相手の背景を知っているだけで、会話ってもっと楽しくなる気がするんですよね><

これも SPYSEE でやっていきたいことです。

アピールが苦手な人(シャイなあんちくしょう)でも損をしない仕組みを作ること

日本人ってアピールが苦手な人って多いじゃないですか。

もちろん、アピールが得意な人もたくさんいますが、あまり自分から自分を推し出すことをしない人が多いですよね><

そんな人を見るとなんとなく「もったいないなあ」と思います。

だから、そんな人たちがもっと損をしない仕組みを作っていきたいのです。

その昔、ホームページに人を集めるためには自分で必死にアピール(登録型リンク集に登録したりとか)しなければいけなかったですよね。それが、今では様々なソーシャルネットワーク検索エンジンによって、面白いコンテンツを作っていれば自然と人が集まってくるようになってきてると思います。

それが、人に対しても起こせるのではないだろうかなんて思っています。

面白い人であれば、自然と注目が集まっていくようなそんなサイトを作っていきたいです><

最後に

SPYSEE は、インターネットを使っている全ての人に使ってほしいサービスです。

だから、このブログを読んでいるすべての人が「ターゲットユーザー」です。

僕は、まだまだインターネットのことをちゃんと分かっていないと思っています。

だから、皆様の意見がすごく聞きたいのです><

それを取り入れながら、少しでも良いサイトを作っていけたらなあと思っています!

少しでも何かアイデアや思うことがあったら何でも気軽に教えてください!

あ、最後に言い忘れてた><

ストリートファイター4で負けてくれる人、募集中です!

f:id:amachang:20100922112742j:image

あ、あと

弊社の見学、勉強会、交流会などもお待ちしております〜。

ではでは!

今日も元気よく!

シュシャ──c⌒っ゚Д゚)っ──!!

2010-09-19

ツイッターのふぁぼられ時間表に色を付けてみた

はじめに

何曜日の何時ごろにどれだけふぁぼられているかも表にしてみました。

Twitterで最もふぁぼられる時間帯は? - さまざまなめりっと

おおおお。おもしろーい。

と、言うわけで

じゃーん、色付けしてみた。

10 fav 以上

f:id:amachang:20100919083852p:image

50 fav 以上

f:id:amachang:20100919083853p:image

おおお

色を付けると見やすいですね。

昼ごはんの帯と、うっすらと起床時間の帯が見えてますね。

やっぱり、金曜日だけピーク時間がちょっと早いんですねえ。すごく意外な感じがします。

みんな、金曜は楽しい気持ちで早くねちゃうのかなあ。

色付け用ブックマークレットはこちら

javascript:(function(s){ s.src = 'http://amachang.sakura.ne.jp/misc/maname_table_color/maname_table_color.js'; document.body.appendChild(s); })(document.createElement('script'))

元のページに行って、ロケーションバー(URL が書いてあるところ)に貼り付けてエンターキーを叩くと色付けされます!

でも、 IE では動きません><ごめんなさい><

2010-09-17

サイボウズで学んだこと

はじめに

2010 年 9 月 15 日を持ちまして、サイボウズ・ラボを退職いたしたました。

報告も兼ねて、久しぶりにブログを書いてみたいと思います。

f:id:amachang:20100917141933j:image

(写真はゆうすけべーさんです)

この会社に入って、たくさんの学びと思い出がありました。

その一つ一つをまとめていければ、素晴らしい記事になるのかもしれませんが、僕は文章が苦手です。

ですので、うまく退職のエントリを書き上げることができません。

言葉にできない。そんな感じです。

なので、このエントリはサイボウズ・ラボやサイボウズ本社の仲間たちへのありがとうの気持ちをこめて、自分らしく最後まで JavaScript のことを書きたいと思います。

サイボウズでの最後の仕事

僕にとって、サイボウズでの最後の仕事は「JavaScript で新しいユーザーインタフェースを作ること」でした。

そして、その中で始めて複数人による大規模な JavaScript の開発というのを行いました。

大規模と言っても、ソースコード一万〜二万行程度、プログラマー 3 人くらいの規模なので、「大規模」というと違和感のある人も多いかもしれません。

ただ、僕の中では人生で一番大規模な JavaScript の開発であったことは間違いありませんでした。

このような機会は、なかなかないと思いますのでこの開発で学んだことを書いていきたいと思います。

大規模 JavaScript 開発の中で学んだこと

大規模な JavaScript 開発で様々なことを学びました。

  • JavaScript という自由度の高いプログラミング言語の中でどうやってコードを共有していくか
  • デバッグをどのようにやっていくか
  • パフォーマンスチューニングをどうするか

大まかにいうとこの三点でしょうか。

JavaScript という自由度の高いプログラミング言語の中でどうやってコードを共有していくか

JavaScript は非常に柔軟で自由度の高いプログラミング言語です。

たとえば、 jQuery で書く JavaScript と Prototype.js で書くJavaScript のコードが全然違うものに見えるように様々な指向の書き方をすることができたりもします。

そのような状況ではコードがぐっちゃぐちゃになりやすいです。

なので、その対策として以下のことをやりました。

  • 基本ライブラリの統一
  • 名前の規則を作る
  • ファイル間の依存解決をライブラリに任せる(自分で script 要素を書かない)
  • 概念を「絵に描いて、説明できる」ということを重視する
  • 複雑な処理は、共通の書き方にする

まあ、あたり前といえばあたり前のことばかりですね。

基本ライブラリの統一

JavaScript では、外部ライブラリというと「基本ライブラリ」「応用ライブラリ」の二つに分類されます。

  • 基本ライブラリ
    • 特定の機能というよりは、プログラミング自体を簡単にするためのライブラリ
    • 基本的に「基本ライブラリ」はページに一つだけ
    • 基本ライブラリ同士は、一緒に使うと DOM 2 Event 周りの API で不具合を起こすことがある
    • 例えば jQuery 、 Prototype.js 、 Google Closure 、 Dojo toolkit などなど
  • 応用ライブラリ
    • ある特定の機能を持ったライブラリ
    • シンプルにその機能だけを実装したものが多く、有名どころの基本ライブラリとは衝突しないように作られていることが多い
    • 例えば Scriptaculous 、 JavaScript User Agent Identfier 、 JavaScript-XPath などなど

サイトで一つの「基本ライブラリ」をちゃんと決めて開発しようね。ということです。

まあ、当たり前っちゃ当たり前っですね。

今回は「Google Closure」を使いました。

理由は「機能豊富で、やりたかったことが出来たから」です。

でもやっぱり、人によっては「あー、 jQuery 使いたいよー><」「俺は、やっぱり Base2 だぜー」とかってなるので、そこはがまん、が、がまんで><

名前の規則を作る

あまり、やりすぎると窮屈にはなるのですが、やっぱり複数人でやるときは必要なんだと思いました。

たとえば、

// クラス名はクラスはアッパーキャメルケースで書く
// 名前空間は小文字
goog.provide('cybozu.ui.Component');
goog.require('cybozu.mixin');
goog.require('cybozu.assert');
goog.require('goog.event.EventHandler');

// 省略可能な仮引数には、最初に opt_ を付ける
cybozu.ui.Component = function(element, opt_name) {
    this.eventHandler_ = new goog.event.EventHandler(this);

    this.element_ = element;
    this.name_ = opt_name || '';
    this.child_ = new cybozu.ui.Component(element.firstChild, 'child');

    // イベント名はロワーケース
    this.eventHandler_.listen(child, 'dragentertochild', this.handleDragEnterToChild, false);
    this.eventHandler_.listen(child, 'dragexittochild', this.handleDragexitToChild, false);
};

cybozu.mixin(cybozu.ui.Component.prototype, {

    // 将来変更する可能性のある名前(プライベートな名前)には最後に _ を付ける。
    status_: 'none',

    hoge_: 'fuga',

    element_: null,

    name_: null,

    // 変数名、メソッド名、プロパティ名はロワーキャメルケース
    evenetHandler_: null,

    getHoge: function() {
        return this.hoge_;
    },

    // イベントなどのコールバック(イベントハンドラ)として使われる名前には、最初に handle を付ける
    handleDragEnterToChild: function(evt) {
        this.enterChildOver();
    },

    handleDragExitToChild: function(evt) {
        this.exitChildOver();
    },

    // ユーザーインタフェースの部品の状態が変化した場合に呼ばれるメソッド名には、最初に enter を付ける。
    enterChildOver: function() {
        DEBUG && cybozu.assert(this.status_ === 'none');

        this.status_ = 'childover';
        this.element_.className = 'childover';
    },

    // 逆に状態をニュートラルな状態に戻す場合は、最初に exit を付ける
    enterChildOver: function() {
        DEBUG && cybozu.assert(this.status_ === 'childover');

        this.element_.className = 'none';
        this.status_ = 'none';
    },

    // 状態の確認は isIn を付ける
    isInChildOver: function() {
        return this.status_ === 'childover'
    }
});

のコメントに書いてあるような名前付けでやります。

ファイル間の依存解決をライブラリに任せる(自分で script 要素を書かない)

JavaScript の処理系は、 PHP の require_once のようにファイル間の依存関係を解決する方法を持っていません。

もし、依存解決をやりたければ、外部のツールや JavaScript 自身に任せる必要があります。

あまり JavaScript を使っていないページの場合、とくに依存解決などはしなくても自分自身で読み込む JavaScript を手書きすることで解決できますが、大規模な開発だとそういうわけにもいきません。

ファイル間の依存解決の方法は、以下の 3 とおりあります。

方法開発時リリース時特徴
同期 XMLHttpRequest と eval×eval なので遅い。eval する箇所のスコープの影響を受ける。依存関係は、実行時に計算される。依存関係の変更があった場合などに何もしなくていいので、開発が楽
動的 script 要素挿入事前にファイル間の依存関係の情報を JavaScript で読める形のデータにしておく必要がある。依存関係が変わる度に、依存関係データを更新する必要がある。
依存するすべてのファイルを一つに結合×無駄なコストが一切ないので早い。コードを少しでも変更したら再結合する必要がある

開発時には「同期 XMLHttpRequest と eval」か「動的 script 要素挿入」が出来て、リリース時には「依存するすべてのファイルを一つに結合」が出来ることが望ましいですね。

ちなみに Google Closure では「動的 script 要素挿入」と「依存するすべてのファイルを一つに結合」が出来ます。

Dojo Toolkit は「同期 XMLHttpRequest と eval」と「依存するすべてのファイルを一つに結合」が出来るんだったと思います、たしか。

概念を「絵に描いて、説明できる」ということを重視する

JavaScript では、様々な書き方が出来るのですが、今回はクラス指向で書いて、 prototype の書き換えや無名関数も基本的には使わないというルールでやりました。

なぜ、そのようにしたかというと「概念を絵に描いて、説明できる」ということが重要だと考えたからです。

クラス指向だと UML っぽい書き方もしやすいですしね。

あと、「様々な状態にあえて名前を付ける」ということもやりました。これも、状態遷移図や状態マトリックスを描きやすくするためです。

あと、「単純なコールバックよりも、イベントを使う」ということもやりました。これも、「イベント名」という名前を付けてシーケンス図が描きやすくするためです。

あとは、親と子をあえて明確にしたり、とか、イベントを listen する対象を親と子だけに限定したり(兄弟への listen は親を経由する)とかですかね。

複雑な処理は、共通の書き方にする

これは、まあ当たり前のことっちゃ当たり前のことなんですが、まあ有り体に言えば「JavaScript でよく出てくるようなデザインパターンは使おうね。」ということです。

たとえば Deferred なんかがいい例かもしれません。非同期処理のエラー処理を書くときに便利ですね。

デバッグをどのようにやっていくか

デバッグは、特に大規模開発には関係ないかもしれませんが。みんなでノウハウを共有しておくことは重要です。

特に今回の開発で役にたったデバッグノウハウをまとめておきます。

アサーションを使う

ユーザーインタフェースのようにテストしずらいコードでは、アサーションを使うとコードの質を効率よく改善できます。

アサーションというのは、「このコードを実行してるということは、事前にこういう状態になっているはず」ということを確認するためのコードを埋め込むことをいいます。

例えば、以下のような assert 関数を作り、

function assert(condition, opt_message) {
    if (!condition) {

        if (window.console) {

            // メッセージの表示
            console.log('Assertion Failure');
            if (opt_message) console.log('Message: ' + opt_message);

            // スタックトレースの表示
            if (console.trace) console.trace();
            if (Error().stack) console.log(Error().stack);
        }

        // デバッガーを起動し、ブレークする
        debugger;
    }
}

こうしておくと、前提条件が崩れた時点でデバッガー起動し、ブレークするので、不具合を調べるのが楽になります。

また、この関数を呼び出す際に以下のように、グローバルなフラグかなんかを使ってリリース時は呼ばないようにしておくといいでしょう。

var DEBUG = true; // 開発時は true 、リリース時は false にする

Component.prototype.handleMouseOver = function(evt) {
    // 開発時だけアサーションする
    DEBUG && assert(this.element_.className === 'out');
    this.element_.className = 'over';
}

様々な条件がある場合は、様々な条件をまとめて一つの名前をつけて、その名前を「状態名」とします。

そして、その条件が満たされたときに「状態名」を変更し、その条件を必要なときに「状態名」を確認するようにします。

Component.prototype.enterDragOver = function() {
    // 状態名の確認
    DEBUG && assert(this.status_ === 'dragging');

    // 状態名を設定
    this.status_ = 'dragover';

    // 状態 dragover が満たすべき様々な条件を設定
    this.element_.style.background = 'red';
    this.element_.style.border= 'blue 1px solid';
    this.element_.style.boxSizing = 'border-box';
};
エラーメッセージを見たら、即座にブレークポイントの条件を考える

alert デバッグ、 console.log デバッグ、 debugger デバッグなどのソースコードを直接書き換えるデバッグはやめましょう。

で、もっぱら「条件付ブレークポイント」を使います。

条件付ブレークポイントは、 Firebug と Webkit で出来る以下のようなやつです。

f:id:amachang:20100917134739p:image

JavaScript でよく見るエラーから、「ブレークポイント」の条件を推測します。

熟練された JSer はエラー名からブレークポイントの条件を即座に答えられる。

たとえば、

hoge.js の 121 行目で「TypeError: Cannot read property 'firstChild' of null」というエラーが出たら

hoge.js の 121 行目を見る

そして、 firstChild というプロパティを読んでいる変数を探す。

で、以下のようになっていたとする。

121: return nodeA.firstChild || nodeB.firstChild;

と、するとここの行で使うべきブレークポイントの条件は「nodeA === null || nodeB === null」ですね。

そんな感じです。

「条件付じゃないブレークポイント」を使ってしまうと、不具合じゃないケースでも止まってしまってわずらわしいので「条件付ブレークポイントを使いましょう」

パフォーマンスチューニングをどうするか

パフォーマンスチューニングに関しては以下のことを気をつけました。

  • 最初から細かいチューニングに気を使うな
  • 決定的に遅くなることはやらない
  • 体感速度の改善を先にやる
  • パフォーマンスチューニングはピンポイントで
  • Google Closure Compiler を使う
最初から細かいチューニングに気を使うな

最初から細かいチューニングに気を使う必要はありません。

細かいチューニングは、あとからなんとでもなります。

決定的に遅くなることはやらない

とは言っても、ある程度の気遣いは必要です。

「DOM を全部走査しないと実現できない機能」などのように明らかに遅くならざるを得ないようなことは、最初からやってはいけません。

体感速度の改善を先にやる

ユーザーフィードバックが足りてない場合や、過度にアニメーションを使うと体感的に遅く感じます。

先にそこから手をつけましょう。


パフォーマンスチューニングはピンポイントで

実行時間の大半は、ごく一部の箇所で浪費されていることが多いです。

なので、パフォーマンスチューニングはピンポイントで効率的にやりましょう。

JavaScript のコードのパフォーマンスチューニングには、 Firebug や Webkit のプロファイラを使いましょう。

f:id:amachang:20100917140444p:image

また、コードが原因とも限りません。

サーバーのレスポンス時間を改善したり、サーバーへ XMLHttpRequest を投げる粒度を調整したりいろいろやることはあります。

全体を俯瞰するには WebKit の開発者ツールの timeline が便利です

f:id:amachang:20100917140443p:image

Google Closure Compiler を使う

Google Closure Compiler を使うと、まったく使われていない無駄なプロパティへのアクセスとかも消してくれたりするので便利です。

まとめ

と、いうわけでサイボウズ・ラボ、サイボウズの皆様、本当にいろいろなことを勉強させていただき、いろいろなわがままを聞いてくださり、ありがとうございます。

このような会社に勤められたことを僕は誇りに思っています。

また、僕の書いたコードを引き継いでくれた @yo_waka id:ama-ch ありがとう。

そして、このブログを読んでくれた皆様、サイボウズJavaScript を書いてみませんか?

ではでは、また id:amachang の次回作にご期待ください。

f:id:amachang:20100917141740j:image

みんな!またね!