Hatena::ブログ(Diary)

Hacking My Way 〜 itogのhack日記 RSSフィード Twitter

2014-03-26

Boltsフレームワークで非同期処理を書く

先日、ParseからBoltsというフレームワークが発表されました。発表された時に機能をさらっと見た感じだとJSのpromiseがJavaで使える!continueで繋げるのね、ふむふむーこれは便利ーって思ったんだけど、実際使おうと思ったらけっこう理解が難しかったのと、Parseのクラスを使った例が多くて汎用的に使う例がおまけっぽくしか書かれてなかったのだ誰でもわかるBoltsの説明をしてみます。

準備

以下からBolts-Android.tar.gzをDLして展開し、bolts.jarを取得したらプロジェクトに追加し、ビルドパスを通しておきます。

https://github.com/BoltsFramework/Bolts-Android/releases


実装

Taskの使い方

タスクというとAsyncTaskのdoInBackground()のように、中にメソッドを持っていそうな気がするのですが、BoltsにおけるTaskは非同期処理の管理をするクラスで、JSのPromisesのJava版という感じです。Promisesって名前にしてくれればよかったのにね!

まずはJavaで普通に非同期処理をするメソッドを作ってみましょう。

public void asyncMethod(final String param) {
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
  // 実際の処理はここで終了
}
}).start();

return ; // このメソッド自体はすぐにリターン
}

Taskに非同期処理の管理を任せるにはこのメソッド内でTaskのインスタンスを生成してメソッドの戻り値でtaskを返し、処理が終了するところでsetResult()でTaskに通知します。

public Task<String> asyncMethod(final String param) {
	final Task<String>.TaskCompletionSource task = Task.<String> create();
	new Thread(new Runnable() {
		@Override
		public void run() {
			Log.v(TAG, "Running task (" + param + ")");
			try {
				Thread.sleep(1 * 1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			task.setResult(param);
			// エラーの場合はsetError()
			//task.setError(new RuntimeException("An error message."));
		}
	}).start();
	return task.getTask();
}

呼び出し側は返ってきたTaskのcontinueWith()メソッドで終了後の処理を書きます。

asyncMethod("hoge").continueWith(new Continuation<String, Void>() {
    @Override
    public Void then(Task<String> task) throws Exception {
        // 非同期処理の実行が終了した
        Log.v(TAG, task.getResult());
       return null;
    }
});

continueWith()の引数に渡せるのはContinuationというインターフェースを実装したインスタンスです。

JavaだとGenericsとかでどうしても見づらいところはありますが、asyncMethod()が終了したところで then()が呼ばれます。

メソッドチェーンでつなぐ

この場合非同期処理が単発なので、スレッド内に終了後の処理を書くのとそんなに変わらないのですが、この非同期処理を連続させてみるとどうでしょう?

同じメソッドを、パラメータを変えて連続で読んでみます。

public void runChainingTasks() {
	asyncMethod("foo")
			.onSuccessTask(new Continuation<String, Task<String>>() {
				@Override
				public Task<String> then(Task<String> task) throws Exception {
					return asyncMethod(task.getResult() + "bar");
				}
			}).onSuccessTask(new Continuation<String, Task<String>>() {
				@Override
				public Task<String> then(Task<String> task) throws Exception {
					return asyncMethod(task.getResult() + "baz");
				}
			}).continueWith(new Continuation<String, Void>() {
				@Override
				public Void then(Task<String> task) throws Exception {
					Log.v(TAG, "Chain finished : " + task.getResult());
					return null;
				}
			});
}

このようにネストせずに書けます。ネストではなくメソッドチェーンで書けるというところがポイントです。

これをJavaで普通に書こうとすると、以下のようにどんどんネストしていくことになり、書くのも面倒だし可読性も悪くなっていきます。

public void pyramidAsync() {
	new Thread(new Runnable() {
		@Override
		public void run() {
			// do something 1
			new Thread(new Runnable() {
				@Override
				public void run() {
					//do something 2
					new Thread(new Runnable() {
						@Override
						public void run() {
							// do something 3
						}							
					}).start();
				}			
			}).start();
		}
	}).start();
}

複数タスクを連続実行する

非同期処理の数が増えるとこのTaskの利点が活きてきます。

上記のメソッドチェーンと基本は同じですが、forループ内でtaskに.continueWithTask()をつなげていくことで、ある処理をが終わったら次の処理を、それが終わったらまた次を、というように連続して非同期処理を実行できます。

public Task<String> series(List<String> results) {
	Task<String> task = Task.forResult(null);
	for (final String result : results) {
		task = task.continueWithTask(new Continuation<String, Task<String>>() {
			@Override
			public Task<String> then(Task<String> task) throws Exception {
				return asyncMethod(task.getResult() + ", " + result);
			}
		});
	}
	return task;
}
複数タスクを同時実行する

複数の処理を同時実行する場合、whenAll()というメソッドを使えば、すべての処理が終了した時の待ち合わせが出来ます。

Taskのリストを作って、whenAll()に渡します。

public Task<Void> parallel(List<String> results) {
	ArrayList<Task<String>> tasks = new ArrayList<Task<String>>();
	for (String result : results) {
		tasks.add(asyncMethod(result));
	}
	return Task.whenAll(tasks);
}

ソースはこちら

https://github.com/itog/BoltsAndroidSample

2014-03-11

TestFlight買収に見る無料サービスの怖さ

なにかが「無料」ある場合にはなぜそれが無料なのかを十分に考えないといけない。

ケータイ端末が無料なのは、通信料など他の費用でその分を回収しているから、というのは比較的分かりやすいが、これがウェブサービスとなるとけっこう複雑になってくる。

GoogleはGmail, Google Drive, その他さまざまな質の高いサービスを無料で提供しているが、それらにかかる費用は広告によってもたらされた利益で賄われている。GmailはともかくGoogle Driveなどは検索とは直接関係がない。Googleほど有名であれば、彼らが検索連動広告で無尽蔵の収入を得ているから、とわかるのだが、利益構造のわからない会社が無料でこれほどのサービス提供していたとしたら、なにか裏があると思ったほうがいい。

よくあるのが、個人情報を収集されているとかそういった類のものなのだが、スタートアップが提供しているサービスの場合はちょっと状況が違う。

スタートアップ提供しているサービスは、利益は度外視してユーザ数やPVなどを増やし、規模が十分になってからビジネスモデルを考えるという戦略をとっている場合が多い。一定の容量だったり回数まで無料で使え、それ以上を求めるユーザから課金するフリーミアムモデルが定番だ。

利益が出るまでは増資によって資金調達するので、直近で収益がなくても特別裏があるわけではない。

ParseというBaaSサービスがある。2013年4月にFacebookに買収されたが、2011年までに$7Mを調達し、優秀な技術者を多く抱え、REST APIからiOS, Android, JavaScriptなどの各種でほぼ同機能でかつエレガントなクライアントAPIを提供していた。

Parseのビジネスモデルはフリーミアムモデルだ。スケールするビジネスなので最初は赤字でもユーザを獲得していく必要があるので、無料でも充実した機能を提供していたし、有料プランもちゃんと用意されていた。

Facebookに買収された後も、とくにFacebook色に染まることもなく、それまでと変わらずサービスが続いている。


TestFlightを2012/3に買収したBurstlyはそれまでに$7.3Mを調達しているので当面は赤字でも良いサービスを提供しているし、普通に資金調達は出来るだろうと思っていた。

買収から1年後には、サービス拡大路線を示す様に、はAndroid版を公開。

https://twitter.com/itog/status/306253802061848578

ところが、、、TestFlightは、無料プランしか持たなかった。

たとえ売上が小さかったとしても、有料プランあるいは他の収益構造がないというのは不自然だった。有料プランがいつ発表されるのか、どの様に課金されるのかというのはずっと気になっていたのだけれど、まさかの結末を迎えることになる。

突然Android版終了のお知らせ。

この時点では原因がわかってなかったので、ユーザの声が上がれば存続の可能性もあるんじゃないかと思っていたんだけれど、Appleの買収されることが明らかに。

最近は先のParseの例のように、買収をしても元のサービスを継続する例が多い気がしていたのだが、iOSとAndroidのようなドコンペティター関係だと致し方ない。先に有料プランがあれば、少なくとも契約期間内はサービスを継続しなくてはならなかったかもしれないけれど、そんなことを言っても後の祭りだね、、、

無料ツールにはこういった危険があることも意識しておかなくてはいけない。

開発ツールの囲い込みは、競合側の開発者にとってはかなりの嫌がらせ。Appleがこういうことをやってくるということは、逆にGoogleが仕掛ける場合だって考えられちゃうね。これを期に、AppleとGoogleによる開発者支援ツールの奪い合いが始まってしまわないことを願います、、、

2014-03-10

GenymotioでGoogle Play Servicesを使えるようにする

Androidの開発環境の不満の一つにエミュレータの動作が重い、ということがある。iOSのシミュレータが軽快に動くのと比較され、Androidがdisられる要員の一つになっている。

実機がいつも手元にあればいいのだが、端末ごとに挙動の違う問題を解決するために、さまざまな画面サイズやその他スペックの端末を常に手元に持っておくというのは現実的ではない。

そこで導入したいのがGenymotion.

GenymotionはAndroidのX86エミュレータだ。SDKに含まれているARMのエミュレータに比べると格段に動作が機敏で通常の開発マシン上で十分実用出来る。

http://www.genymotion.com/


このGenymotionを使う上で大きな問題が一つある。それは、Genymotionで実行出来るイメージにはGoogle Play Appsが入っていないため、Googleライブラリを使ったアプリをインストールしようとすると以下のエラーが出てインストールできない。

INSTALL_FAILED_MISSING_SHARED_LIBRARY

同様に、X86のためARMを条件としているアプリもインストールできずに下記エラーとなる。

INSTALL_FAILED_CPU_ABI_INCOMPATIBLE

以下手順でこれらのエラーが出なくなる。

ARM Translation, Google Appsインストール手順

  1. ARM Translation Installer v1.1

Google Apps for Android 4.x (必要なバージョン)

  1. 以下のファイルをDLする
  2. Genymotion VMを起動してホーム画面にします
  3. Genymotion-ARM-Translation.zipをGenymotion VMにドラッグアンドドロップします。
  4. “File transfer in progressが表示されたあとダイアログが出るのでOK

f:id:itog:20140310115400p:image:medium

  1. 以下adbコマンドでGenymotion VMを再起動します。

adb reboot

  1. 再びホームスクリーンを開いて今度は先ほどDLしたGoogle AppsのzipをDrag&Dropしてダイアログが出たらOK
  2. 終了したら再起動します

基本これでOK。Google PlayでGoogleアカウントにログインしてアプリを更新しておくほうが良い。


参考)

http://forum.xda-developers.com/showthread.php?t=2528952

2014-01-26

行動が価値を生む

いつも自分が思っているのとが書かれてたので訳してみた。

http://blog.samaltman.com/value-is-created-by-doing

2chに書き込みしたり、ツイートしたり、他社の資金調達に関するニュースを読んだりコーヒーを飲んだり、、、これらは本当の仕事ではない(もしこれらのことを仕事だと思うのなら、仕事で生み出す価値についてもっと深く考えてみるべきだ)。それらにも多少は意味がある。ネットワーキングをし、さまざまなアイディアに触れることは必要だが、それ自身からは富が生み出されるわけではない。

価値は会社が製品を作った時や、それを顧客に販売したときに生じるものだ。おおまかなガイドラインとして、自分がやろうとしていることに近いところにいるといいだろう。

もちろん、正しい行動をしなくてはいけない。誰も必要としないソフトウェアを書いても価値は生まれない。それは学校の授業だ。だから、なにをするかを決めるのは非常に重要だ。そして戦略は、ピボットによって成功した会社が持っているだろうとあなたが思っているよりも重要だ。しかしながら、戦略はそれだけでは価値を持たない。価値は実行することで生まれるのだ。

スタートアップを始めることについて話すのは、実際に始めることよりも簡単だ。そして話しているうちは楽しい。しかし時間が経つにつれ、楽しいことと充実することの違いは明確になる。行動を起こすことはとてもキツイ。だから、あなたの仕事についての一般的なことはNDAなしで話していいし、ほとんどの特許は問題にならない。価値と、その難しさは実行するときになってやってくる。

自分自身に正直になる秘訣がある。私が会社を営んでいたとき、一日の最後に、今日なにをしたかをリストアップしていた。とても忙しいと感じた日の夜に、なにもやってないと悟ることが目立った。同じように、ちょっと忙しいと思う程度の日に3つ4つの大きなことを達成した日もある。

問題に関係する仕事に集中し、他のことは忘れるのだ。もしくはMachiavelliの言うように、

「怠けて失敗するのではなく、大志を抱いて失敗せよ。苦しみに耐える力ではなく、勇敢なことを行う力を身につけよ」

人には計測すると、それを増加させようという傾向がある。毎日のミーティングの数で生産性を測るのであれば、ミーティングの数は増えていく。利益の増加や決まった投資額などで測れば、ミーティングの数は減っていくだろう。

‘not-quite-work’の他の例はサンフランシスコで毎晩行われている。ディナーパーティーに集まって未来の言を話す。とても楽しいが議論になることはない。ほとんどの人はいつか人類は宇宙に行く必要があるということには同意するが、パーティーが終われば家に帰って別のことをする。

宇宙に行くことが人類にとって最も重要なことだと思うのならば、それをやればいい。何百億円もの資金の集め方がわからないのであれば、SpaceXのようなすでにある会社に入ればいい)。エンタープライズソフトが本当に好きならば、それをやればいい。

今これを呼んでいて非生産的だと感じるのであれば、それは良い兆候だ。ブラウザを閉じてしまおう。良いニュースをひとつ。軌道修正して、いい気分になるのは簡単だ。

2014-01-07

シリコンバレー基準でのFourBeatの評価

しばらく経ってしまったんだけど11月にSF Japan Nightというピッチイベントのためにサンフランシスコに行ったとき、決勝の前日だか前々日にSan MateoのDraper Nexusで行われたピッチイベントにも参加した。

面白いことに、このイベントではジャッジの採点がビジネス、テクノロジー、プレゼンテーションの3つの項目事の点数として公表されたので、それをレビューしておこう。

f:id:itog:20131105203554j:image

FourBeatの採点、順位は以下のとおり。

Business2.3314/15
Technology2.8312/15
Presentation3.509/15
Total8.6612/15

まずビジネスの評価が低い。これは実際に弱いところで今後力を入れていかなければいけないところだろう。

次にテクノロジー。ピッチではあえて技術的な説明は少なくしているのだが、それだとこういう評価になるのか。ちなみにRingの4.33が最高点。

プレゼンテーションにはMaker Faireの時のいつもの動画を使ったのでその評価がプラスになったのだろう。

ピッチ後の審査待ちの時間にはもちろんFourBeatで遊んでもらった。マッチョな奴らが夢中になってるのウケるw

雑感

コンテストは「airbnbの家庭料理版」と言える、Feastlyが優勝した。いかにもSVぽいサービス。

このピッチにはSF Japan Night決勝のために来た5チームが含まれていたのだが、僅かさの2位だったRingを除いて総じて評価は低かった。語学の壁もあるかもしれないが、発表慣れというかジャッジが必要としている情報を織り込んでいるかどうかというところが大きい。

プレゼンのフォーマットについてはこれが基本なんだけど、それぞれをどう伝えるかというところでもう一段掘り下げたフォーマットがあるように思う。

終了後、ジャッジの一人から聞いたところ「日本のチームはみんサービス紹介をしているだけ」というような印象が共通の見解としてあったようだ。発表する方にしてみれば急遽知らされたイベントだしプライズがあるわけでもないので目標設定が難しかったというのもあるかもしれないが、発表者はそういうのを言い訳にしてはいけない。

この時知り合ったGLIPHのオフィスに後日遊びに行ったのだが、このチームは投資を受けるまでにピッチを80回以上はしたのだそうだ。

それが良いか悪いかではなく、SVのピッチコンテストに参加するということはそういう準備をしてきているチームと同じ土俵に上がることなんだということは意識しないといけないだろう。

おまけ

Draper Nexusの受付にはテスラの車の筐体が使われた受付が。

f:id:itog:20131105205152j:image:w360

f:id:itog:20131105205139j:image:w360

あわせて読みたいブログパーツ テクノラティのお気に入りに追加する