ソフトウェアエンジニアに大切なこと

プログラミングという名の魔法

Web Api Hackathon Vol.3に参加してきました

晴海で行われたWeb Api Hackathon Vol.3 - connpassに参加してきました。
今回はTechcrunch Tokyoとは違って1日のみのHackathonです。
内容はAPIを叩けばなんでもOKというゆ〜るい感じでとても好感が持てますね。

朝10時前に会場近くに到着しました。
晴海って初めて行ったんですが、高層ビル立ち並ぶオフィス街って感じでした。
ちなみに会場も37階(!)で絶景でした。
そんなこんなで会場に行こうとしたんですが、
目的のビルは見つかったもののどこから入ればいいかわからない!
日曜日の朝だったのであたりは人気が少なく、
運良く見つけたサービスセンターっぽいところのお姉さんに会場の入り方を聞き、会場へGO。
お姉さんありがとうございました。

ビルの入口で偶然主催者の方と出会い、案内して頂きました。
会場に入るとまさにスタートアップ、卓球台やソファーが畳の横に並んでいました。
ここで作業できるのかと思うとテンション上がる!コーヒー飲み放題!

開始時間になってから主催者の方々から説明、諸注意を受け、チームビルディング開始。
僕は

  • 他の人が今どこでどんな作業をしているかわかる。
  • それによってリアルでの技術者の出会いが促進される

という技術者出会い系サイトの「reatech」
アイディアを出していた河合さん、後デザイナーさんとでチームを作ることになりました。

まず最初に環境を合わせようということで、ruby2.0, rails4.0.1, postgresで開発を進めることになりました。。が、wifiが遅かったのが原因かもしれませんがbundleに異常に時間がかかって思うように作業が進まない。。
そうこうしてるうちに昼食タイム。あと6時間で物を作らなければいけません。
想定している機能は

  • チェックイン、チェックアウト
  • アクティブなエンジニア一覧
  • アクティブなプロジェクト一覧
  • Google Mapでの俯瞰

を想定し、各自がそれぞれやりたいところをやるという非常に柔軟な姿勢で開発していきました。
すぐに破綻しそうですが、意外とうまく行ったのはメンバーの力量が高かったおかげだと思います。
発表スライドなんて用意もせずぎりぎりまで開発を続けた結果、チェックイン、チェックアウト、Google Mapでの俯瞰の3機能を「厳密な操作」で実行可能な状態に持って行くことが出来ました。
いやあ、やればできるもんだ。

デモの時間では河合さん主導で実際に参加者に触ってもらおうとしましたが、、先走って操作を間違える人続出でエラーページを見ることに。みんな、落ち着くんだw
だから厳密な操作が必要だとあれほど(ry

デモはいまいちうまく行きませんでしたが、個人的には今回のハッカソンは自分の目指しているものと目標が近くてとてもおもしろかったです。
ハッカソン後の懇親会でも河合さんと「エンジニアとはなんだ」みたいな抽象的な話で大いに盛り上がり、開発以外でも得るものが大きかった一日でした。

これだからハッカソンはやめられない。
もっとたくさんの人と会って一緒に開発したいものです。

再帰じゃないフィボナッチ数

フィボナッチ数列っていうのがあります。

フィボナッチ数 - Wikipedia

再帰の実装サンプルなんかでよく使われるアレですが、普通に実装すると簡単に処理できなくなるアレです。

よくある実装はこんなかんじですよね。

def fib(n):
  if n == 0 or n == 1:
    return 1
  return fib(n-1) + fib(n-2)

定義の通りに書いた感じです。これを手元のマシンで実行したところ、n=40ほどでもう帰ってこなくなりました。

では次に、メモ化による高速化を行うとどこまでいけるのでしょうか?

上記のサンプルでn=40で戻ってこなくなるのは、同じ計算が多すぎるからです。

なので特定のnに対するfib(n)の値を保存しておけば同じ計算を省くことができます。

memo = {}
def fib(n):
  if n == 0 or n == 1:
    return 1
  if n in memo:
    return memo[n]
  memo[n] = fib(n-1) + fib(n-2)
  return memo[n]

これでn=40どころかn=500くらいまでは計算できるかと思いますが、n=1000となると、今度は再帰が深すぎることによるstack overflowが起きます。

末尾再帰最適化があればそれで実装するのもひとつの手ですが、そもそもフィボナッチ数列を実装するにあたり、再帰は必要なかったりします。

フィボナッチ数列は定義の通り、fib(n)はfib(n-1)とfib(n-2)のときの値のみから算出できます。言い換えると、fib(n-1)とfib(n-2)の時の値を何処かに保存しておけばfib(n)を計算できるはずです。

この考えに基づいた実装がこれです。

def fib(n):
  a = 1
  b = 1
  for _ in xrange(n-1):
    a,b = b,a+b
  return b

aがfib(n-2)の値、bがfib(n-1)の値です。

それぞれ初期値fib(0)、fib(1)で初期化し、n=2以上からループに入ります。

ループの中ではaは計算前のbすなわちfib(n-1)の保存に使用し、bはa+bすなわちfib(n-1)+fib(n-2)の計算に使用します。

1ループが終了するとき、a=fib(n-1), b=fib(n)となっているので、次のループに対するnにってはa=fib(n-2), b=fib(n-1)となります。

これで反復のみの実装となったので、n=100000位はいけますかね。

TechCrunch Tokyo 2013 hackathonに参加してきました

11/11, 12に開催されたTechCrunch Tokyo 2013でhackathonに参加してきました。

嵐の前のチームビルディング

最初に主催側の挨拶、進行、ルール説明がありました。

こういう機会を設けて頂いてありがとうございます。

今回のhackathonでは提供されるAPIのどれかを使ってプロダクトを作ることが条件となります。優勝チームには30万とMA9決勝への出場権が与えられます。

提供されるAPI

  • Gracenote:音楽認識WebAPI
  • トヨタ:IT開発センター車載API
  • KDDIウェブコミュニケーションズ:TwilioAPI
  • PUX(Panasonic 任天堂JV)顔認識API
  • Docomo API
  • Philips HUE

その後各自画用紙に名前、できること、その時点での興味等を書いて見せ合う形で自己紹介。

ひと通り終わったら各自注目した相手と話し合ってチームを作っていきます。

僕は最初hueに興味があってメンバーを探していたんですが、自己紹介で優勢だったのはトヨタとPUXだったように思います。

周りの人の考えを聞いているうちに時間がなくなってしまったので、拾ってもらう形でチームに入れて頂きました。この時点でのチームは暫定で、アイディアソンの結果を踏まえて移動してもOKとのことでした。

混迷のアイディアソン

ぞれぞれがそれぞれのチームを作ってアイディアソンに入りました。

僕のチームはやることがまだ決まっていない状態で、APIを見てやりたいことを出していきました。

とりあえずメンバーのノリがやばかった。

恋愛系の方向に偏ってからは意見が出るわ出るわで、もはや発表止められてもいいかっていう方向に向かっていたw

ちょっとここでは書けないレベルでの会話で、周りから聞かれていたら完全に変態扱いだったように思います。

アイディアソンの結果発表、つまり何作るか宣言は無難なものに落ち着いたのだけれど、後に実際作るものとはかけ離れたものでした(詳細忘れた)。

宣言が終わってから暴走しつつも「これで本当に進むのか?」と少し冷静になりました。

改めて使える材料を見なおしたところ、HUEが結構レアでここでしか使えないであろうということで、HUEを題材に練り直すことに。ここで最初にHUEに興味を持ってたことを思い出す。

色々なアイディアが出たけれど、音楽によって色を変える、などすでにあるようなものしか出てこなくて煮詰まりました。

ここでメンバーの一人から、メールのやり取りで相手の実際の感情が読めない時があり、そのときに光の色で伝えてやれば面白いのではないか?というアイディアが出ました。

これは僕も思い当たることがあり、真っ先に賛成、メンバーの同意も得られ、大筋は決まりました。

次はどうやって光の変化のトリガーを与えるか、という話になりましたが、色々なAPIを使った入力を考えた結果、相手の表情からそのときの感情を認識し、それをトリガーにすれば面白いという結論になりました。

では何の表情が何の色を示すか?と考えてるうちに、実際の表情認識結果を絵として表示すればより直感的になるのでは?という意見が出て、結果、あれ?HUE使わなくね?という結論にw

予めHUEを借りてたのですが、最終的には使用しませんでした。アドバイスを頂いたHUEのの方々有難うございました。

(個人的に)苦難のハッカソン

アイディアが固まり誰が何をするかを決めます。

作るものは相手の表情がわかるチャットシステム「DoyaChat」

チャットのリレー及び顔認識はサーバ側で、チャットの実行と顔のキャプチャはAndroidでやることになりました。

実はすでにサーバ側とAndroid側で精通しているエンジニアがいて僕のやることがないという状況にw

やれることがないので保険的に、少し自信がないというAndroidによるフロントカメラを使用した定期的な顔キャプチャの実装をすることになりました。

しかし僕にはAndroidの経験がない。

初めてのAndroid開発を時間が限られているハッカソンでやるという愚挙に出るw

しばらく触った結果、Activityからバックグラウンドで動作するServiceを呼び出して、その中で定期的にカメラを実行してやればいい、というところまでわかりました。

のだが。。何度やってもtakePicure failedが出てServiceで実行することができない。

ここまでで初日は終了。どう考えても後数時間では時間が足りない(ハッカソン発表は二日目午後3時から)ので、各自深夜作業することで一旦解散。

家に帰ってしばらくAndroidと格闘していると、トラブル発生。

USBデータ転送ケーブルを認識しなくなった!?

充電もできないことや、他のガラケでは充電できることからAndroidのusb端末故障を疑いましたが、一縷の望みを掛けてコンビニへ新しいUSBデータ転送ケーブルを探しに行くことにしました。午前二時に。

まあコンビニにあるわけないんですが。コンビニにあるのは充電用ケーブルで、Androidのデバイスデバッグにはデータ転送ケーブルが必要です。

しょうがないのでapkを毎回作ってAndroidにダウンロードすることに。

しかしあまりに効率が悪く、寝落ちにつながりました。。

 

次の日起きたのは9時。始まるのは9時半。普通に遅刻。終わってるな、自分

Facebookグループで謝ってからできるだけ早く渋谷へ。

がしかしまたしてもここで障害が。

東横線直通のどこかで事故が発生して、各駅で運転見合わせ!?

正直仮病使って休もうかと一瞬考えましたが、さすがに外道すぎるので別ルートで迂回して渋谷へ。10時半着。

状況を確認させてもらうと、なんとAndroidのカメラまわりも実装済みとのこと。

SUGEEEEEEEEEEEE

役立たずすぎて内心落ち込んでましたが、メンバーの優しい言葉で救われました。

何かできないことはないかと思い、色々仕事を探していると、結果発表の準備をすることに。AndroidエミュレータPowerPointを安定して実行できるのを考えると、僕のMBAが最適のようでした。

全然貢献できてなくて、これだけは絶対成功させたくて本当に一生懸命やりました。

Android側のソースをもらってビルドとエミュレータ実行を何度か繰り返しているうちにようやく期待通りの動作が手元で実現できるようになりました。

サーバ側の実装はまだ残っていましたが、順調に見えました。

結果発表

結果発表の前に接続確認をしました。動作事態は問題ありませんが、出力解像度が低くて、デフォルトではエミュレータの下部が切れてしまうという問題を発見しました。

これの対処はそう難しくなく、エミュレータ起動時のscale設定でなんとかなりました、が。。

そのとき問題が!

メンバー間で「デモ中に無線切れたら終わりだよねー」とか言ってたら本当にその時にwifiが一瞬切れました。wifi自体はすぐに回復しましたが、それがどう影響したかエミュレータ上のアプリでエラーが出て実行できない状態に。

後30分というところでの出来事でした。

それからは、キャッシュクリア、アンインストール、ワークスペースクリア、再インストール等様々なことを試しましたが実行不可能な状態が続いてました。

発表順も後ろに回してもらい、もう時間がありませんでした。

これが最後の試行ということで最も時間がかかるエミュレータ再起動に賭けました。

再起動後、アプリの起動でエラーが出て「あ、駄目か・・」と諦めかけた瞬間、正常動作のログが!

正常動作に必要な処理でエラーが出ているので動くはずがないのですが、何故か動いているというよくわからない状態ですw

それでもデモに必要な動作も確認できたので、これでいくという意思決定をメンバー間で行いました。

そのときの資料はこちら

超かっけー!

デモもうまく行き、反応も良かったと思います。

思いますっていうのはもうドキドキで、上手くいくのを願ってそれどころじゃなかったっていうのが正直なところです。これでこけると僕の存在価値ありませんでしたから。

結果。。

なんとAppSocially賞を頂きました!

この結果に少しでも貢献でき、とても嬉しかったです。

所感

今までいくつかハッカソンに参加してきましたが、一番役に立ってなくて、一番大きな結果を残せた今回のハッカソンです。

そして一番楽しめたのも今回だったと思います。

今回のチームは本当にメンバーが最高で、それぞれがカバーしあって目的を達成出来たのが大きいと思います。

メンバーの誰かが「このチーム面白い。このメンバーでスタートアップしてみたいなー」って言ってましたが、僕もそう思いました。今回のハッカソンは最高の経験でした。

 

Java初心者はstatic使うな!

ジュニアエンジニアのソースコードをレビューしていてよく思うことは 「よくわかってないのにstatic使うんじゃねえ!」

staticが危険なのは複数スレッド間で共有されるという点です。 thread-safeという言葉が密接に絡んできますね。

では具体的に何が問題か? thread間で共有されるとどういう現象が起こるか、と考えるとわかりやすいですね。

たとえば、thread1からあるオブジェクトを「変更している間」にthread2から参照するとき、「変更されつつある中途半端なオブジェクト」が参照される可能性があります。

 Javaは高速ですが、時間を無視して動くわけではありません。 操作には必ずその実行時間が存在します。

これ系で有名なのはSimpleDateFormatですかね。 ご存知なければググってもらえるとわかりますが、thread-safeでないためこの問題が起こり得ます。 ちなみにthread-safeでない旨はjavadocに書いてます。

staticを使用することでnewするコストを省けるのは確かなんですが、個人的にはstaticによるチューニングは後回しでいいと思います。

それよりも、よりバグの少ないプロダクトを作るほうが重要。 しかもstaticが原因のバグはマルチスレッド関係なので検証しづらいですね。

そんなわけで、そもそもマルチスレッドやthread-safeという言葉を理解していない初心者にはstaticを使わせないのが無難です。

staticを使わずを得ない状況では、共有するオブジェクトが本当にthread-safeか、マルチスレッド処理を理解してるメンバーがサポートする必要があるでしょう。