Previous month:
April 2007
Next month:
June 2007

「パラメーターのプロパティ渡し」でプログラムを読みやすくする、というアイデアはどうだろう

 先日の金魚シミュレーターのソースを整理していて思ったのだが、コンストラクターにごちゃごちゃとパラメーターをたくさん渡すとものすごくプログラムが読みににくくなる。そこでフと思いついたことがあるので書いてみる。

 例えばFishというクラスがあったとしよう(ちなみに、これはActionScript3.0)。

class Fish extends MovieClip {
    public function Fish(speed:int, direction:int, x:int, y:int, minDistance:int, maxInfluence:int) {
        this.x = x;
        this.y = y;
        ....
    }
}

 コンストラクター側はこれでも問題はないのだが、呼び出す方がこんな感じになってしまう。

 var f:Fish = new Fish(2, 180, 20, 20, 16, 40);

 C++とかJavaで良く見るプログラミングスタイルだが、こうやってひたすら数字だけが並んでいるとやたらと読みにくい。三日後に見たらどのパラメーターが何なのかが思い出せなくて、コンストラクターのソースコードを参照せねばならない。

 そこで、ActionScriptにもJavaScriptのように自由にプロパティを追加できるObjectというクラスがあることを利用して、これらのパラメーターを一つのオブジェクトのプロパティとして渡すように変更してみた。

class Fish extends MovieClip {
    public function Fish(param:Object) {
        this.x = param.x;
        this.y = param.y;
        ....
    }
}

 すると呼び出し側はこうなる。

 var f:Fish = new Fish({speed:2, direction:180, x:20, y:20, minDistance:16, maxInfluence:40});

 ずっと読みやすくなったように私には思える(ちなみに、これはActionScript版のJSONである)。

 もちろん、実行効率は悪くなるし、プロパティのスペルを書き間違えた時にコンパイラーが警告してくれない、などの欠点もあるが、それほど実行効率が重要ではなくて(=富豪プログラミング)、呼び出し側のプログラムの読みやすさの方が重要な場合には、こんなプログラミング・スタイルも悪くないと思ったしだいである。


ネットが進めるノウハウのコモディティ化

 昨日のエントリーには、たくさんのブックマークをいただいたが()、興味深いのはそこで引用したCraig Raynoldの論文にもたくさんのブックマークが付いたという事実だ()。1987年のSIGGRAPHで発表された論文が、こんな形で「再発見」されて若い学生や技術者たちに読まれることになる、というところが何とも言えずに楽しい。私から見れば「『群れ』のシミュレーションが作りたいならRaynoldの論文を読めば良い」などという情報は「知っててあたりまえの常識」なのだが、知らなかった人にとっては「貴重なノウハウ」なのだ。

 「インターネット以前」は、この手の情報共有はものすごく難しかった。それどころか、逆にこの手の情報を会社の内部ですら「自分だけのノウハウ」として抱え込むことによって差別化を計ろうとするせこい技術者がたくさんいた。つまり、「他の人が簡単に手に入れることができない知識・情報を持っていること」がその人の人材市場における価値を高めることに直結していたのだ。

 ネットの時代になって一番大きく変わったのは、そういったノウハウのコモディティ化が始まったことである。これだけネットに情報があふれてくると、この手のノウハウを自分に抱え込んでいるメリットがどんどん少なくなってくる。それに加えて、ブログを通じてどんどんと情報を発信する側に立った方が、自分にとっても勉強になるし、より多くの情報が集まってくると考えるブロガーが少しづつだが増え始めたのだ。

 今の時代のすごいところは、999人の人がノウハウを抱え込もうとしても、たった1人のブロガーが公開してしまえばそれだけでコモディティ化が一気に進む点である。そうやってさまざまなノウハウがネットを通じて共有され、人類全体の財産として継承されて行くのである。なんとも痛快な時代になったものだ。


ネットの時代には「知識量・記憶力」よりは「適応力・応用力」の方がずっと大切

 先日の「習作UI: 縁日の金魚を再現してみた」というエントリー。特に深い意味もなく作ったのだが、ソフトウェア・エンジニアを目指す学生さんのためにひとこと付け加えておきたいのは、この業界で本気で成功しようと思ったら、この程度のプログラムは、シミュレーションの専門家でなくともサクッと作れるように自分を鍛えておかなければいけない、ということ。

 この業界で働きはじめると、担当した仕事によって、データ解析・Java・3D・シミュレーションなどのある特定の分野のプログラミングの経験を積むことになる。そういった経験を通して特定の分野を深堀りしてエキスパートになるのはおおいに結構なのだが、往々にして落ち込んでしまうのが「ボクはJavaのエキスパートだからRubyではプログラムは書かない」、「シミュレーションのことならそれに詳しいエンジニアがいるんだからその人に頼んで」、「今からFlashを勉強している時間はないからActiveXで作らせて」などと融通の利かないことを言う「使えないエンジニア」になってしまうこと。これでは時代の変化についていけない。

 私のマイクロソフト時代の同僚に、インドから来た飛び切り優秀なエンジニアがいたのだが、彼に言わせると「どんな技術でも二週間でマスターしてみせる」。かなり自身過剰なセリフだが、本当にすごい奴で、そんな彼との仕事は楽しくてしかたがなかった。

 ちなみに、このプログラムに関して言えば、数年前に空を飛ぶ鳥の群れの動きを再現するプログラムの存在を知り、その時に見つけたのが「Flocks, Herds, and Schools:A Distributed Behavioral Model」という論文。それを読んだときにそのアルゴリズムのシンプルさに感動し、「機会があったら自分でも書いてみよう」と心にブックマークをしておいたのである。

 そして今回、Flashのプログラミングを勉強し始めたを良い機会に、この金魚シミュレーターを作ってみたわけであるが、アルゴリズムを覚えていたわけでもないので、「flock simulation」でサーチをして再度この論文を見つけだして、もう一度読み直してからこのプログラムを書いたしだいである。

 学生諸君にぜひともお願いしたいのは、この手の課題にどんどんと取り組んで「新しい技術をすばやく習得して応用する」テクニックを見につけることである。知識や情報そのものはネットを探せば簡単に見つかるので、自分の脳みその中に知識を溜め込んでおく「記憶力」や「知識量」はあまり役に立たない。それよりは、必用に応じて新しい技術をすばやく検索・吸収し、実際のプログラムに応用する、という「適用力」・「応用力」のほうがずっと重要である。

 で、君たちの作った金魚、そろそろ泳ぎ始めていますか?


習作UI: 縁日の金魚を再現してみた

 Flashでプログラムを書く機会があったら一度は作らねばと思っていたのが、鳥や魚の群れ(flock)のシミュレーション。そこでカスタムクラスのプログラミングの練習も兼ねて作ったのがこれ。アルゴリズムそのものは、良く知られた(1)仲間と同じ方向に泳ごうとする気持ち、(2)仲間と一緒に泳ごうとする気持ち、(3)衝突を避ける気持ち、をそれぞれの魚に持たせて泳ぐ方向を少しずつ変化させる、というものである。

 プログラムはそれほど時間をかけずに作ることができたのだが、苦労したのがそういった「気持ち」の部分を表現するのに必用な具体的なパラメーター(どのくらい離れた仲間まで認識しているか、どのくらいの距離までの接近を許すか、など)を見つけ出す部分。金魚すくいの水槽の中の金魚の動きをちょうど良い感じで再現するためのパラメーターを見つけるのにかなりの試行錯誤が必要であった。

 しかし、これを作って思ったのは、Flashの開発環境は水と油で作ったドレッシングのようだということ。デザイナー向けの機能(keyframeとtweenを使ってmovie clipを作る部分)と、プログラマー向けの機能(ActionScriptを使ってインタラクティビティを実現する部分)の両方をキチンと使いこなすのは結構難しい(この例では、個々の金魚の尾びれの動きはmovie clipを使って実現しているが、泳ぎの方向の決定とフレームごとの位置の移動はActionScriptを使って実現している)。

 本来なら、こういったインタラクティビティの部分こそUIデザイナー自身がデザインしながら作るべきなのだが、この開発環境だとその部分はプログラマーに頼らねばならないのが残念なところだ。まあ、そのおかげで私みたいな「UIプログラマー」が職にありつけるのだから個人的には悪くないのだが、やはり開発ツールを作る仕事をしている私としては、「デザイナー自身がプログラムを書かずにインタラクティブなアプリケーションを作れる環境を提供せねば」とつくづく思ったしだいである。

 ちなみに、金魚を実際にすくうことは出来ないが、ちょっとしたお遊びインタラクティビティの機能も追加してみたので、マウスを水槽の上で動かしてみて欲しい。


習作UI: 初めてのFlash その4

 ひさしぶりの連続エントリーとなってしまったが、最初に自分にあたえた「24時間以内にそれなりに遊べるパズルゲームを作る」というゴールをこれで一応達成。昨日の写真を移動・完成させるPicture Controlを再利用してパズルを作っただけのことである。

 パズルの目的は、この4つのピースを並び換えて「大文字のT」を作ることである。先日とあるところでこのパズル(手で触ることができるもの)で遊んだのだが、それがとても楽しかったので、今回の習作の課題に選んだのである。

 正解にたどり着いたかどうかの判定ロジックはついていない。「作るのが面倒だった」という事情もあるが、あえて判定のロジックなどつけずにどんどんコンテンツ(つまり、並び換えるべきピース)を増やしていく方が今の時代に合っているのではないかと思っている…それもユーザーの力を借りて(CGM!)。リアルの世界のパズルやゲームもこの「ルール判定」や「終了判定」の部分は人間に頼っているものが大半であるし。

 ちなみに、今後これをどうやってCGM的なサービスとして展開させていくかに関してはこれから考えて行きたい。「ソースコードは公開したので後は自分で作ってください」では敷居が高すぎるので、何とかして誰にでも簡単にコンテンツ作りができてしまう仕組みを作りたいと考えている。


習作UI:初めてのFlash その3

 「ソース公開希望」というコメントをいただいたので、さっそくソースを公開。なにしろ、ActionScriptをさわったのは今日が初めてなので、何かとんでもなくまとはずれなことをしている可能性もあるので、そこは御容赦のほどを。

 ソースコードを公開するだけでは十分ではないところがFlashの悩ましいところだが、とりあえず作り方を説明しておく。

1.移動用の丸を描き、Moverという名前のButton Symbolに変換する。そして、Overのkeyframeの時のみその丸を表示するようにしておく。ちなみに、アンカーが中心になるようにしておく。
2.回転用のドーナッツを描き、Rotatorという名前のButton Symbolに変換する。同じく、Overのkeyframeの時のみそのドーナッツを表示するようにしておく。やはり、アンカーが中心になるようにしておく。
3.Mover、Rotatorのインスタンスを一つづつ作り、それを二つ合わせてPicture Controlという名前のMovie Symbolにする。やはり、アンカーが中心になるように配置しておく。
4.Moverのインスタンスを"mover"、Rotatorのインスタンスを"rotator"という名前にしておく。
5.Picture Controlのインスタンスをダブルクリックして、Edit in Place状態にする。
6.Scriptという名前のレイヤーを追加し、下のソースコードをActionとして貼り付ける。
7.トップのステージに戻り、適当な大きさの画像をインポートする。
8.インポートした画像と、Picture Controlのインスタンスを合わせてMovie Symbolに変換する。
9.それ(インスタンス)をダブルクリックして、Edit in Place状態にし、アンカーが中心になるように配置する。
10.他の画像も貼り付けたければ7~9をさらに繰り返す。

 これで完成である。アンカーの位置がちゃんと中心になっていないと、座標計算が狂うのでそこだけは注意していただきたい。ActionScript3.0で書かれているので、CS3以前のものでは動かない(はず)。私はAdobe Flash CS3 Professionalを使っているので、Basic版で同じことが可能かどうかは未確認である。

//----------------------------------------------------------------------
// Global variables for "Mover" (some of them are shared)
//----------------------------------------------------------------------
var dragging = false;
var anchorX, anchorY;
var relX, relY;
var pictureFrame;

//----------------------------------------------------------------------
// Event handlers for "Mover"
//----------------------------------------------------------------------
function dragBeginHandler(event:MouseEvent):void {
    dragging = true;
    anchorX = event.stageX;
    anchorY = event.stageY;
    pictureFrame = event.target.parent.parent;
    relX = pictureFrame.x - anchorX;
    relY = pictureFrame.y - anchorY;
    stage.addEventListener(MouseEvent.MOUSE_UP, dragEndHandler);
    stage.addEventListener(MouseEvent.MOUSE_MOVE, dragMoveHandler);
}

function dragEndHandler(event:MouseEvent):void {
    dragging = false;
    stage.removeEventListener(MouseEvent.MOUSE_UP, dragEndHandler);
    stage.removeEventListener(MouseEvent.MOUSE_MOVE, dragMoveHandler);
}

function dragMoveHandler(event:MouseEvent):void {
    if (dragging) {
        pictureFrame.x = relX + event.stageX;
        pictureFrame.y = relY + event.stageY;
    }
}

mover.addEventListener(MouseEvent.MOUSE_DOWN, dragBeginHandler);

//----------------------------------------------------------------------
// Global variables for "Rotator"
//----------------------------------------------------------------------
var rotating = false;
var anchorA, offsetA;

//----------------------------------------------------------------------
// Event handlers for "Rotator"
//----------------------------------------------------------------------
function rotBeginHandler(event:MouseEvent):void {
    rotating = true;
    pictureFrame = event.target.parent.parent;
    relX = event.stageX - pictureFrame.x;
    relY = event.stageY - pictureFrame.y;
    anchorA = - Math.atan2(relX, relY) / Math.PI * 180;
    offsetA = pictureFrame.rotation;
    stage.addEventListener(MouseEvent.MOUSE_UP, rotEndHandler);
    stage.addEventListener(MouseEvent.MOUSE_MOVE, rotMoveHandler);
}

function rotEndHandler(event:MouseEvent):void {
    rotating = false;
    stage.removeEventListener(MouseEvent.MOUSE_UP, rotEndHandler);
    stage.removeEventListener(MouseEvent.MOUSE_MOVE, rotMoveHandler);
}

function rotMoveHandler(event:MouseEvent):void {
    if (rotating) {
        relX = event.stageX - pictureFrame.x;
        relY = event.stageY - pictureFrame.y;
        var rot = - Math.atan2(relX, relY) / Math.PI * 180;
        pictureFrame.rotation = offsetA + (rot - anchorA);
    }
}

rotator.addEventListener(MouseEvent.MOUSE_DOWN, rotBeginHandler);


習作UI:初めてのFlash その2

 ネットで探してみると、マウスのキャプチャーの仕方が判明。ホットスポットへのMOUSE_DOWNのイベントをボタンで受け取ったあとは、(ホットスポットではなく)"stage"(Flashの表示領域全体)へのMOUSE_MOVEとMOUSE_UPイベントをlistenするようにすれば良いだけのことであった(ただし、これだとマウスのボタンを押したまま"stage"の外に出ると挙動が少しおかしくなる→これは別途解決する必用あり)。

 それに加えて、写真の移動・回転をつかさどっている部品を一つの独立したmovie symbolとして再利用可能にした。なんだかやたらとsymbolがネスティングしているが、これがFlash独特のプログラミング・パラダイムなのかも知れない。なぜ「Flashムービー」を作れる人はたくさんいるのに、キチンとした「インタラクティブFlashアプリ」を作れる人があまり多くないのかがだんだんと分かってきたような気がする。


習作UI:初めてのFlash

 訪問先でUIEngineとFlashの違いを良く聞かれるので、それにちゃんと答えられるようにとFlashの勉強を始めた。これが一番最初の作品。写真を動かしたり回転させたりできる。いきなりActionScriptの3.0から入る人も珍しいのかも知れないと思いつつ書いてみた。まだまだ改良の余地はあるが、とりあえず今日はここまで(マウスのキャプチャーのしかたが分からん…ととりあえず書いてみるテスト^^;)。


ドリコムの「ジョブボード」を試してみた

 「なかのひと」サービスを使って、企業からのアクセス一覧を簡単に見ることができるようになってくると(参照)、どうしても考えたくなるのは「このブログを訪れる人たちに最も効果の高い広告は何か」ということである。

 今までAmazonアソシエイトやGoogle AdSenseなどを試してきてつくづく感じるのは、「読者層をはっきりと意識した広告」の効果の高さである。Google Adsenseにまかせっきりの広告はほとんどクリックされないが、書評に貼り付けたAmazonの広告は、単にクリックする人がたくさんいるだけでなく、実際のセールスにもつながる。

 その意味では、一度ぜひとも試してみたかったのが、求人広告。今までも、「就職・転職活動に役に立つブログの書き方」、「『あなたもレールから外れてみませんか』」と言う気もないが」、「知的労働者には『組織を移る力』がある」、「自分がやりたいことと会社にとって必要なことのベクトルを合わせることができた時に大きな力がでる」などの転職をうながすようなエントリーを書いてきたこともあるし、これらのエントリーに対するフィードバックを見てもこのブログにもっとも相応しいのは求人広告ではないかと常々考えてきた。

 そこで試しにドリコムのジョブ・ボードの仕組みを使って月3万円という設定で求人広告を募集してみたところ、ブログパーツとして掲載後わずか二週間で「株式会社ガイアックス」というところから最初の求人投稿の申し込みがあった(感謝・感謝)。この方式の広告が継続的に成り立つかどうかは今後の求人投稿がどうなるかで明らかになることだが、「転職・就職のことを常にうっすらと考えているIT・ネット業界の人たちが読むブログ」というこのブログのポジショニング(^^;)を考えれば、そんな人たちがわざわざ買いもしない求人雑誌なんかよりはずっと効果的だと思うのだがどうだろう(ちなみに、実際の求人広告の投稿は、このエントリーにも貼り付けてあるブログパーツ中のDrecom_3というボタン押すことにより表示されるフォームに必用事項を記入することにより可能である)。


「なかのひと」を使ったアクセス解析の結果を公表してみるテスト

 今月初めに「『なかのひと』を設置して一週間」というエントリーを書いて、「なかのひと」を使ったアクセス解析を始めたこと、およびその結果を公表する予定であることを予告しておいた。

 予想していたとおり「集計結果を公表してしまうっていうのは、無用なトラブルを起こす原因になるような気がします」などの保守的なコメントも書き込まれ、どうしたものかと考えていたのだが、やはりどう考えてもこれが「プライバシーの侵害」にあたるとも思えないし、誰かに直接迷惑をかけるとは思えない。

 ということで、設置後一ヶ月弱でまだ若干ノイズが含まれているかもしれないが、とりあえずベストテンを公開してみる。

1.富士通
2.ソニー
3.日本電気
4.スクウェア・エニックス
5.はてな
6.松下電器産業
7.日本IBM
8.ソニー・コンピュータエンタテインメント
9.ヤフー
10.マイクロソフト

 まあ予想通りと言えば予想通りだが、こんな風に実際にIT・ゲーム・ネット業界の企業が並ぶと何とも…。あまりデタラメなことは書けないなァ^^;

 ちなみに、学校法人では東京大学・大阪市立大学・東京工業大学が14・15・17位と健闘し、母校の早稲田大学は25位である。

 こんな風に企業からこのブログへのアクセスを簡単に目に見える形にしてくれる「なかのひと」サービスにはとても感謝しているのだが、一つだけリクエストさせてもらうとすれば、Excelで解析しやすいCSV形式での出力。アクセス数に応じたソーティングだとか、複数の場所にオフィスのある企業のアクセス数を集約するなどが、もう少し簡単にできると助かる。