プログラミング 美徳の不幸

Ruby, Rails, JavaScriptなどのプログラミングまとめ、解説、備忘録。

六本木のキャバクラっぽいとこに行った

先日、大変めずらしく接待をしていただく機会があって、シースーからの六本木のキャバクラっぽいところに行った。

寿司のほうは恵比寿にあるランチのコスパが良いことで評判の店で、数カ月前に別の機会で行ったこともあっただけ新鮮さはなかったが、キャバクラ自体初めて行ったのとその店のシステムが独特だったのでここに記したい。

といってもさすがに店名や画像など、実物を出してしまうとつまらないのでイメージでお楽しみいただく。


ここは六本木のとある雑居ビル。階段を登ると一見店舗には見えない重厚な扉。

なかを開けるとスキンヘッドの男、黒人、そして奥には何人もの若い女性が。

この店に連れて来てくれたAさんはだいぶ常連のようで、店中の女の子がAさんに挨拶する。当然だが僕はしどろもどろでカオナシのように「あっ・・・あっ・・・どうも・・・」としかしゃべれない。

店を見渡すと他に客はいない。事前にAさんはこの店はボッタクリだと言っていたが、ボッタクリ店の傾向そのものだ。

ほかに客がいないためかサービスがいい店なのか、男一人に対して2,3人のコンパニオンが着いた。私はキャバクラの経験がないのでよくわからないが、普通は1対1くらいなんじゃなかろうか。

で、露出度の高い服(といっても普通のドレス)を着た女性が左右についた。左のほうは関西弁でミソノに似ていたのでミソノちゃんと呼ぶ。

右のほうはブラジル人で名前はアンジェリカちゃん(仮)としよう。

さっそく私の緊張はピークに達し、まず何を聞けばよいかもわからず、さらにこのブラジル人はどの程度の日本語まで大丈夫なんだろうかとか、そういうのを探ろうと思った。

「最近ブラジル経済大丈夫? オリンピックもIMFがさぁ...」

アンジェリカ「オニーサン難しいネー、そういうのわからないヨー!!」

さっそく空振ったようだった。ただ収穫としてアンジェリカは日本語自体は問題ないようだ。 私はとりあえず共通の話題を探すべく、二分探索の要領で「本はよく読むか」「映画は好きか」などの問いを繰り出してみようと思った。 しかしこれが大失敗だ。なぜなら、そもそもあの人たちにNoという答えはないからだ。興味があろうとなかろうととりあえず当たり障りなく好感触を演出する。

こうやってブラジル人との意思の疎通?に四苦八苦しているうちにさらなる重大な問題に気づいた。

(ミソノと全然しゃべってない!!)

左右に女性がいるとどうしてもどちらかに意識が集中する。さらに音がガンガンうるさいので(余談だが追悼なのかデビッドボウイが流れてた)距離を保って3人で話すような雰囲気ではない。

そこで今度はミソノに切り替えてみる。

「関西弁かわいいね! ずっと関西だったの?」 ミソノ「そうやねん、うち大阪やねん!」

あぁ、何のひねりもない展開だ。そもそも自分で振っておいてなんだけど僕は関西一帯に興味があまりないのでほとんど行ったことがないし、大阪と兵庫の区別も付かない。大阪といえば・・・と頭をめぐらしてみたが真っ先に浮かんだのは橋下徹大阪維新の会だった。 「大阪維新の会支持してるの?」とか言おうかと思ったが、先の反省からこの店で政治と経済の話題は不可能だと判断し、大阪トークからは撤退しさりげなくアンジェリカのほうに会話を戻した。

とまぁこういうふうに会話に苦労しているうちになんだかんだ1時間くらい経ったら音楽が切り替わりショータイムというか、ハッスルタイム的なものに移った。

アンジェリカ「お兄さん、イクヨ!」 ミソノ「立って!」

両脇を抱えられ立つように促される。あぁ、そういうことか、だから一人10万もするって言ってたのか。唐突なことで分からなかったが場の空気、「心の準備はできてるか」などのフレーズから確信した。

このまま別室に行き、この二人と熱い夜を過ごすのかと・・・。

そうするとなぜか二人は私を別室でなく、ホールの中央にある何やら丸いお立ち台のようなとこに連れて行く。私は衝撃的な勘違いに気づく。

(別室じゃなくて、この謎のお立ち台で衆人環視のもとヤるのか!?)

途端に私の緊張はピークに達し、アンジェリカ、ミソノ両氏にちょっと気持ちの整理がつかないので待って欲しい旨を伝える。 しかし二人は緊張することはないと促し、とうとう私はお立ち台の上で仰向けになる。

すると、どこからともなく現れたダンサーがお立ち台の上、つまり私にまたがるような格好で踊り出す。しかし期待を裏切って申し訳ないが、このダンサーはこの写真のようにボンテージのようなものを身にまとっているので、全裸を下から覗くようなそういうわけでもない。

まぁ何はともあれさっきの二人でなくこのダンサーとなのか?など混乱していると、ダンサーがしゃがみ込むようにして私の顔を撫でたり頭を触ったりした。それで終わりだ。

全く期待を裏切られた。席に戻って拍子抜けだったとミソノに話すと、「当たり前じゃーん、うち風俗店じゃないんだから〜」。

そりゃそうだけど、ここに連れて来てくれた人も「すごい店。グレーな店。超高い」しか言ってなかったのでそりゃそのくらいのことイメージするでしょうよと。

アンジェリカ「お兄サーン、緊張してるね、勘違いしてるからタバコでも吸って!」

と旧マイルドセブンを差し出してくる。

まぁこれも事前に予習済みだったので、知らない外国人+六本木+タバコ = 大麻だと確信して、「これタバコじゃないやつじゃないの笑??」と牽制してみる。

アンジェリカ「私ハタバコじゃないヤツもヤッテルけど、これはタバコだよオニーサン〜」

いやいや、やってちゃダメだろうと思ったけどそこは社会人なのでクールに受け流す。

まぁ何はともあれ、結局このまま展開もなく解散、帰宅した。

まとめ

六本木は危ないのでなるべく大人の人と一緒に行きましょう

引っ越す

わりとあっという間だが今の住居の契約更新の時期になった。更新料は東京ルールで1ヶ月とよくわからん諸経費が取られてそれだけで16万になる。なんだか最近の生活はかなり微妙だったので、この際早いが思い切って引っ越すことにした。

失敗点

正直、今住んでるところは楽しいこともあったし当時の状況から考えれば理由は確かにあったのだが、大きく見て失敗だったと思う。

◯前回引っ越した時の記事

tkot.hatenablog.com

失敗点1 高い

今の住居は13万で、当時の収入から考えれば5万も10万も15万も同じだなと思っていたのだけど、経済情勢は変わる。というか、ライフスタイルによって必ず貯金が必要なときと、そうでないときが出てくる。そうなったとき、固定費は大敵となる。 まぁ、とりあえずウハウハになったらまたすぐ引っ越せばいいやと思う。

失敗点2 職住合致

当時と今で考えが明確に変わったのはここで、これは人によると思うけど一日中家で仕事は無理だなと思った。こうやってブログ書いたりしちゃうし。。。 というわけで日中家から出るようにします。

失敗点3 矛盾してた

僕の当初の予定はアクセスが良いオフィスっぽいところを借りて、オフィス状態にしてそこに住むというものだったけど、こもって仕事をする以上アクセスが良い必要は全くないのでは・・・

細かい失敗点

終電が遅い

銀座線はすごく気に入ったのだけど、唯一のネックが終電の遅さ。ヘタすれば大宮に帰るより終電早いんじゃないだろうか。11:50くらいになくなる。

港区は税務署のアクセス等が悪い

港区の鉄道網は需要の割には微妙で、意外と陸の孤島のような所も多い。広尾とか(は渋谷だけど、麻布近辺とか)。 で、税務署が遠い。 渋谷区は渋谷駅、豊島区は池袋駅から歩ける。

JR、というか山手線

やっぱり山手線の利用頻度は高いので山手線沿線に住むべきだった

というわけで、まだ未確定ですが2月から職場を渋谷(シェアオフィスだけど)、自宅を池袋にしようと思ってます。今年は経済も冷え込み、もはやリーマン水準並の不況といっていい状態になる恐れもあると思います。消費増税もやめてほしいですね。冬の時代に備える。これがキーワードです。 (そんなこと言い出したら景気悪くなるじゃんって人は政府に財政出動して消費マインドを刺激するよう言ってください)

Google Cloud Storageのモバイル対応は残念な点 およびAmazon Cognitoはすごいという話

今年も年の瀬、最後は一応技術ブログなのでプログラミングの話題で締めます。

モバイルアプリでユーザが画像や動画を投稿するサービスを作る際、バックエンド側のエンジニアが最も腕の見せどころとなるのはレスポンスの早さです。バックエンドにかぎらず、フロントでもバックグラウンドでアップロードさせるとか、細かいローダーをどのように表示するかで体感速度を向上させるわけです。 Amazonではサイトの表示が10ms(=0.01秒)遅くなると売上が~~という話がよくあります。というわけで多くのサイトは200msとか目標を決めてサーバのレスポンスをなるべく早く返しています。だから遅くて1秒、2秒かかるサイトはあっても10秒以上かかるサイトはあまりありません。(ここで言ってるのはサーバの速さです)

一方でモバイルアプリのアップロードはそれとは違い、15秒撮影した動画をアップロードするのに1秒2秒で済むということはありません。iPhone6で加工してない動画を撮影すると1秒あたり2~3MBになりました。 この数字だと回線状態が悪いと10秒とか20秒、あるいはもっとかかるくらいのサイズなのでアップロード中の離脱が増えてしまいます。

モバイルから直接アップロードする

画像や動画をアップロードする際、自社のサービスのサーバ(以降APIサーバ)に送って保存+リサイズ等行うのが多いみたいですが、この方法だとAPIサーバからさらにストレージサービス(s3やGoogle Cloud Storageなど)への転送時間がかかってしまいます。 もちろんこれを非同期にすることは可能ですが、今度はAPIサーバに動画・画像の転送処理というバッチ的な機能を持たせる必要があります。これは例えばRailsAPIを書いてる時、APIサーバ群とバッチ(ActiveJobなど)サーバ群の構成を分けたいときにAPIが一部でバッチ的な役割も担う必要があって見通しが悪くなります。

そこで理論上、モバイルアプリが直接ストレージサービスに画像等をアップロードしてから、そのURLをAPIサーバに送り、さらにバッチサーバでリサイズ等処理をするのが無駄のない処理になります。

このことを言ってくれてるのがこちらの記事です。

qiita.com

で、ここからが本題なんですがs3でできるならCloud Storageでも同様にできるだろうと思い資料を探してみました。 ところが、結論から言えばCloud Storageではこれはできません。(間違ってたら教えて下さい)

そもそもCloud StorageのiOSライブラリはいまだにobjc版だったりARC対応してないなどインストールだけでも大変だったんですが、どうやらAPIの権限上の問題でユーザが投稿することを認めていません。

Cloud StorageのAPIについて

f:id:tkot:20151230221822p:plain

APIのキーがいくつかあって混乱します。 まずセキュリティ上、iOS側に渡しても問題のないキーは一番上のiOS APIキーになると思います。(一応DeNAのプラットフォームの友人に聞いて確認しました) そのほか、例えばサーバキーやサービスアカウントのOAuth認証をユーザに渡すとリバースエンジニアリングのリスクがあるわけです。

で、ポイントはiOS APIキーはサービス全体に紐づくデータやユーザデータに対する権限をあまり持っていないということです。iOS APIキーで調べると一番上にはGoogle Mapのサンプルが出てきます。こういうユーザやサービスにあまり直接かかわらないAPIを操作するためのキーだと思われます。

したがってiOS APIキーではCloud Storageに画像をアップロードすることはできません。

もう一つの方法はユーザがアプリ上でGoogleログインして、アプリに対して認可をくれればそこでもらったOAuthトークンでユーザの画像を作ってやることができますがこれは今回のユースケースとは違うので除外します。

試してないのですがサービスアカウントをハードコーディングせず各ユーザに対して動的に付与してやる方式ならうまくできるのかもしれません。

Amazon Cognito

というわけでAmazon Cognitoの出番です。Cognitoは要するに端末ごとにユーザを識別してくれるサービスです。内部的には初回起動時にユニークIDを付与し、keychainに保存しているようです。

で、ここはわりとブラックボックスになっているのでまだ把握できてませんがCognitoを使えばAWS側が端末を識別できているので、こちらが持っているs3に画像をアップロードできます。

試しに使ってみたら非常にカンタンにアップロードできたので、とりあえず今回はこのアップロード限定でs3を使うことにしました。

Cloud Serviceの一本化/併用は考えて行う

私は普段Google Cloud Services一本なんですが、Googleが持ってないものでAWSが先行しているもの、およびその逆が意外とあることを今回痛感しました。例えばEC2 vs Compute Engineなどはさすがに一本化していいと思いますが、各サービスの利点をうまくとりいれつつ、互いが邪魔しあわないようにうまく住み分け/インテグレートしていくチョイスが今後重要になるのではと思います。

高橋みなみ報道ステーション後任説

f:id:tkot:20151227195307p:plain

www.j-cast.com


まじかよと思ったけど、正直宮根誠司みのもんた福澤朗あたりはすでに見てるからつまんないし、安住アナも土曜日で十分だ。

というわけで久米宏復活か、高橋みなみ起用あたりのサプライズは見てみたいな。

Gemを作って公開する本当のメリット

Gemを作って公開すると、誰かに気に入られると多くの人からスターが付いてPRが来たり、自分の名前が売れる。 それだけで満足感があったり、転職活動に有利なのだけどプログラミング上の本当のメリットは次のようなことだと思う。

  def method_missing(method, *args, &block)
    case method
    when METHOD_PATTERNS[:callback]
      filter = $1.to_sym
      name = $2
      if callback = args.shift
        set_callback name, filter do
          if respond_to?(callback, true)
            send(callback)
          else
            instance_eval(callback)
          end
        end
      end

      if block.present?
        set_callback name, filter, &block
      end
    else
      super(method, *args, &block)
    end
  end

  def respond_to?(method, priv = false)
    METHOD_PATTERNS.values.any? { |pattern| pattern =~ method } || super(method, priv)
  end

ちょっと今仕事で保守しないといけないアプリケーションのソースにこういうのがある。 で、これって書いてる時はいいんだけど読むのは辛いし、読めた所で動的ディスパッチが多いので結局周辺情報まで辿っていかないと意味がなくて、デバッグ上のコンテキストとか依存性が大きすぎるんだよね。

というわけで、ここでエラーが起きたとしてこのコードが間違っているのか、はたまた実行環境(インスタンス変数とかの状態)がおかしいのかがわかんない。

で、Rubyってmethod_missingとか使いまくるとどうしてもこういう傾向が強くなってしまうので、こういうライブラリ的なコードは外において切り離し、他の人や他のプロジェクトから使用してもらって実行環境に依拠せず動くかとか、ライブラリにバグがあったときはレポートしてもらうorあわよくばバグフィックスしてもらって、とにかく自分のビジネスコード側にあたりをつけてデバッグできるようにしたほうがずっと楽なんですよ。

というわけで、こういうコード書く時は小さいgemにして公開しておくのがいいと思います。まぁはっきりいってアプリケーションの中に唐突に出てくるこういうコードはクソースですね。まぁ2年前の自分が書いたんだけど。