漫画のスマホファースト: planetarium – ハシモトスズ

スマホで読める漫画ってありますよね。

各コマを横スクロールして読み進めるタイプ。あれ目が疲れるから大嫌いなんですよ。

タップかスワイプでコマを進めるタイプ。あれも嫌い。何百回とタップさせられるなんて、ありえない!

そんな中、新しいタイプの漫画を見つけました。

Screen Shot 2014-07-16 at 9.42.15 AM

planetarium – ハシモトスズ

コマ割りがほぼ全部タテなのです。
コマごとにタップしなくていいし、横スクロールが無いので目が疲れにくい。
しかも、立てスクロールを活かした特徴的な表現。
めっちゃ読みやすい!!

これは・・!!もしや漫画のスマホファーストでは・・!!と衝撃を受けました。

ぜひこの表現手法が浸透して欲しいものです。

Node.jsにおける大量のデータ処理の際の非同期処理コールバックがスタックしすぎる問題への対処

ストリーミング処理の落とし穴

Mongoose(MongoDBのODM)を使って、コレクションからほんの10万ほどのドキュメントを処理するスクリプトを実行した時でした。処理が固まってしまうのです。なぜでしょう?

各ドキュメント処理では、コールバックを伴う非同期的な処理を含みます。
問題のCoffeeScriptのコードは以下のようなイメージです:

Foo.find()
    .sort value:-1
    .stream()
    .on 'data', (d)->
        someTask d

someTask = (d)->
    doAwesomeJob (result)->
        console.log "Great!"

モデルFooのドキュメントを全て読み込み、各ドキュメントをストリームに流し込んでいます。
メモリを節約するためにストリームの手法を採用しています。
doAwesomeJobは、例えばAPIを叩くとか、そういう非同期な処理です。
しかし、doAwesomeJobのコールバック関数がなかなか呼ばれない。遅い。ついには全く呼ばれなくなる。

イベントループのキューが溢れている

Node.jsアプリケーションはシングルスレッドです。
下図のように、イベントループ機構が備わっていて、Event Queueに溜まった処理キューを順次消化していく仕組みになっています。

event-loop

(via http://misclassblog.com/interactive-web-development/node-js/)

つまり、Node.jsはひとつずつしかキューを処理できないのです。
上記スクリプトで、ストリームのイベントのInvocationが、大量にこのイベントキューに押し寄せている事を想像してください。
doAwesomeJobのコールバックは、その非同期処理の完了時点で最後列にエンキューされます。
しかし、非同期処理の間にドキュメント読み出しイベントの処理キューが大量に溜まります。
その結果、doAwesomeJobのコールバックが呼ばれるまでに時間がかかってしまっているのでした。

似た問題に直面している人がいました。

RabbitMQのメッセージキューがいちどに大量に来た時に、イベントループのキューが溢れるようです。
問題は僕のケースより少し深刻なようです。見なかったことにしましょう

ストリームを分割しよう

溢れるのなら、分割すればいいですね。
以下のように変更を加えました:

processNext = (offset, num, on_completion)->
    i = 0, j = 0, closed = false
    Foo.find()
        .sort value:-1
        .skip offset
        .limit num
        .stream()
        .on 'data', (d)->
            ++j
            someTask d, ->
                ++i
                if i==j && closed
                    processNext offset+i, num, on_completion
        .on 'close', ->
            closed = true
            on_completion() if j==0

someTask = (d, callback)->
    doAwesomeJob (result)->
        console.log "Great!"
        callback()

processNext 0, 100, ->
    console.log "done!"

ドキュメントを100個ずつ読み出して、処理して、終わったら次の100個・・というフローに変更しました。
今のところ、これで上手く動いています。

でもこのコードは少し汚いので、よりエレガントに書くためにasyncを使うことをお薦めします。
drainで完了をフックするといいと思います。

このストリームの分割では、ストリームを処理している間にドキュメントが追加・削除される事を想定していません。
コレクションの変更まで考慮する場合は、想定される変更内容によって変わると思います。

ご参考まで!

[iOS] Swiftの隠し機能:数学記号をカスタムオペレータとして使う

swift-book

新言語Swiftでは、C++のようにカスタムのオペレータを定義できます。
このオペレータには、Unicodeの文字が使えるとのこと!
下記のツイートのような感じで使えるらしいです。

let r = ¬(a ∧ b)

詳しい例はこちら:

https://gist.github.com/mattt/f457625af116721ffb57.js

Vineで見つけたおもしろ動画まとめ

trademark_logo

Vine面白いですよね。
ついつい気づいたら1時間とか見てしまってます。
中高生のアホなテンションがたまらん。
海外のも含めて、笑えるやつ、興味深いやつ、凄いやついろいろ混ぜてご紹介します。
暇つぶしにどうぞ!


https://vine.co/v/Mrrhn62TmYF/embed/postcard

//platform.vine.co/static/scripts/embed.js

続きを読む Vineで見つけたおもしろ動画まとめ

[iOS] アカウント情報をアプリ間で安全に共有する方法

keychain500x500

はじめに

google-642x309

Google Drive, Docs, SheetsのiOS版では、アプリ間でGoogleアカウント情報を共有しています。
いずれかのアプリで一度認証すれば、他のアプリでは面倒な認証手順が不要になります。
これはどういう仕組みで行われているのでしょう?
アプリはどのようにして、ユーザの入力無しにユーザを識別しているのでしょう。

Keychain:安全に機密情報を取り扱う仕組み

実は、先に述べたGoogleのアプリ達は、KeychainというOSの仕組みを使っています。
Keychainは、もしあなたがMac OSXユーザであればなじみ深いと思います。実はiOSにも備わっています。
これは、パスワードや秘密鍵、証明書などの機密情報を安全に管理するための仕組みです。
Keychainで保管されるデータは暗号化されます。

アカウント情報の取り扱いに最適

Keychainと同じようにユーザ情報を保存するための仕組みとして、UserDefaultsというものがあります。
UserDefaultsは、主にプリファレンスなどを保存するための仕組みです。
UserDefaultsと比べて、Keychainが機密情報の取り扱いに優れている点は以下です:

  • アプリが削除されてもデータが残る
  • 同じKeychain Access Groupに属するアプリ同士でアクセスできる (Keychain Access Groupは後ほど詳しく説明します)
  • データが暗号化される

Keychain Servicesとは

Keychain Servicesは、Keychainを使うためのAPI群です。
以下からAppleのドキュメントを参照できます:

Mac OSXとiOSではAPIが異なるので注意です。
ここでは、iOSでの使用を前提として説明します。
日本語の資料では以下が参考になります。

しかしながら上記ページは古くて、XCode上の手順が有効でない部分があります。
本ページでは、XCode 5で設定する場合を説明します。

Keychain Servicesの基本的な使い方

Framework

利用するには、Security.frameworkをプロジェクトに追加してください。

便利なラッパモジュールを使おう

Appleが用意したAPIをそのまま使うのもいいですが、我々には時間がありません。
オススメは LUKeychainAccess です。
LUKeychainAccessを使えば、NSUserDefaultsと同じ感覚でKeychainのアイテムを管理できます。
以降は、このラッパを使う前提で説明します。

基本的な使い方

NSUserDefaultsと全く同じです。

[[LUKeychainAccess standardKeychainAccess] setBool:NO forKey:@"authorized"];
BOOL authorized = [[LUKeychainAccess standardKeychainAccess] boolForKey:@"authorized"];

Keychainでのアクセス制御

制御の軸はアイテムに「いつ」アクセスできるのかと、「どれが」アクセスできるのか、の2つがあります。

Accessible属性

アプリケーションが「いつ」アクセスできるのかを制御します。詳しくはこちら
LUKeychainAccessでは、それぞれ以下の定数で指定できます。

  • LUKeychainAccessAttrAccessibleAfterFirstUnlock
    • 再起動後最初のアンロック以降/次の再起動まで
  • LUKeychainAccessAttrAccessibleAfterFirstUnlockThisDeviceOnly
    • 再起動後最初のアンロック以降/次の再起動まで
  • LUKeychainAccessAttrAccessibleAlways
    • 常にアクセス可
  • LUKeychainAccessAttrAccessibleAlwaysThisDeviceOnly
    • 常にアクセス可
  • LUKeychainAccessAttrAccessibleWhenUnlocked
    • デバイスがアンロックされた状態
  • LUKeychainAccessAttrAccessibleWhenUnlockedThisDeviceOnly
    • デバイスがアンロックされた状態

以下のように指定します。

LUKeychainAccess* keychainAccess = [LUKeychainAccess standardKeychainAccess];
keychainAccess.accessibilityState = LUKeychainAccessAttrAccessibleWhenUnlocked;

Keychain Access Group

「どの」アプリケーションがアイテムにアクセスできるのかを制御します。
デフォルトでは、アクセスできるアプリケーションはそのアイテムを格納したアプリケーション自身だけです。
グループの指定によって、同じグループに属するアプリケーションからのアクセスを許可出来ます。
このグループは、アイテムごとに指定できます。

例えば、あなたのapplication-identifiercom.foobar.applicationだとします。
あなたのアプリケーションが読み書き可能なグループは、そのグループ識別子がapplication-identifier前方一致する場合です。
グループによる権限の違いは以下の通りです。

  • アクセス可なアイテムのグループ
    • com.foobar.application
    • com.foobar
  • アクセス出来ないアイテムのグループ
    • com.apple.calendar
    • com.foobar.mailer

つまり、com.foobarというグループに属するアイテムを作成すると、アクセス出来るアプリケーションはapplication-identifiercom.foobar.*に相当するものになります。

また、注意点ですが、同じグループに属していてもアクセスできない場合があります。
それは、Code Signing Identityがアプリケーション間で異なる場合です。
つまり、アイテムを共有するアプリケーションは同一ベンダーのものでなければなりません

Keychain Access Groupの変更

Keychain Access Groupをデフォルトのapplication-identifierから変更するには、Entitlementsを作成します。
XCode 5ではこの作成手順が簡単になっています。

まず、ビルドターゲットのCapabilitiesタブを開きます。

Screen Shot 2014-07-10 at 12.02.58 AM

Keychain Sharingという項目を見つけたら、スイッチをONにしましょう。
Keychain Groupsというリストが現れたはずです。
ここに、指定したいグループの識別子を入力します。
グループは複数指定できます。
一番上に記述したものが、デフォルトで使用されるグループになります。

シミュレータにおけるグループの取り扱い

シミュレータでも動作しますが、テストは実機でやる事を強くおすすめします。
というのは、シミュレータだと常にグループがtestとなるからです。
シミュレータ上では、グループ指定に関わらず全てのアプリケーションから全てのアイテムにアクセス出来ます。

TestFlight用ビルドとデバッグ用ビルド間ではアイテムを共有出来ない

ここで、TestFlight経由でインストールしたビルドと、USB経由でインストールしたビルドのapplication-identifierを別々にすればテストできるかもしれないと思いますが、これも無理です。
理由は、Code Signing Identityが異なるからです。
共通のCode Signing Identityで、異なるapplication-identifierのアプリを用意しましょう。

アイテムのキー

基本的な使い方のセクションで説明した通り、アイテムのキーは単純な文字列で指定できます。

[[LUKeychainAccess standardKeychainAccess] setBool:NO forKey:@"authorized"];

これは以下のような単純なkey/valueストアです。

key = value

Keychain Servicesでは、この単純なキーに加えて、オプションでサービス名も付けられます。
以下のようにserviceディレクトリにkey/valueを格納していくイメージです。

service.key = value

サービス名の指定は、TwitterやFacebookの認証情報をセットにして格納したい場合に便利です。

サービス名つきアイテムへのアクセス方法

残念ながらLUKeychainAccessは、サービス名の指定にまだ対応していません。。
そこで、このラッパをフォークして対応させてみました。

サービス名対応版なら、以下のようにサービス名を指定できます。

[[LUKeychainAccess standardKeychainAccess] setBool:NO forKey:@"authorized" service:@"Twitter"];
BOOL authorized = [[LUKeychainAccess standardKeychainAccess] boolForKey:@"authorized" service:@"Twitter"];

簡単ですね!
本家にはこの拡張をプルリクエストしておきました。

自前ホストのHubotとSlackを連携させる方法

images hubot-featured

最近、チャットツールをHipChatからSlackに乗り換えました!

Slackとは?

いわゆるチャットツールです。技術者向け。
SlackはHipChatと違ってUIがリッチで分かりやすいです。オシャレ!
HipChatと同じくAPIを備えており、GitHubやAsanaなど様々なサービスと連携させる事ができます。
そして、タイトルにもあるHubotとも連携させる事ができます。

Hubotとは?

チャット上で使えるボットです。Node.jsで書かれています。GitHub社が開発しました。
ボットというとTwitterのボットを想像するかもしれませんが、基本は同じです。
ボットに向けて、決まった書式でメッセージを送ると、そのメッセージに応じた処理を行います。
例えば、Jenkinsのビルドを実行したり、アプリケーションをデプロイしたり、ネコ画像を拾ってきたりします。

Hubotを導入するメリット

従来は個別のターミナル内で行っていたタスク指示が、チャットウインドウに移ります。
この事のメリットは主に二つあります。

  1. 作業ログが残る
  2. チームとのコミュニケーションと作業が統合される

ビルドやデプロイなどは、いつ誰がやったのか残っている事が望ましいです。
また、チームワークにおいてはそのタスクが属人的にならないようにする事が重要です。
タスク実行をチャットウインドウから行う事で、直接的な作業が会話にシームレスに混ざります。
それによって、デプロイなどの手順や気をつけるべき点が自然と共有される形になります。

このようにチャットを使ったサーバ運用をChatOpsと呼びます。

Herokuではなく自前サーバのHubotと連携させたい

Slack用Hubotプラグインがあるので、書かれている手順に従えば簡単に設定できます。
日本語の情報もnanapiなどに掲載されています。
しかし、どれもHubotをHerokuにデプロイする場合の手順です。
いやいや、俺は自前サーバにHubotを稼働させる場合の手順が知りたいんだ
という訳で、このページでは自前ホストのHubotとSlackを連携させる手順について説明します。

Hubotのインストール

既に自前サーバで動作している方は読み飛ばして下さい。

  • Hubotをインストール
    $ npm install -g hubot coffee-script
    
  • botの作成
    $ hubot --create [path_name]
    $ cd [path_name]
    
  • Slack用アダプタのインストール
    $ npm install hubot-slack --save
    
  • 試しにローカルで起動
    $ ./bin./hubot
    

Slackとの連携設定

Slackの以下のページから、環境変数に設定する値を取得します。

Screen Shot 2014-07-08 at 11.15.43 PM

それぞれ、環境変数に設定します。

$ export HUBOT_SLACK_TOKEN=<token>
$ export HUBOT_SLACK_TEAM=<team>
$ export HUBOT_SLACK_BOTNAME=<bot name>

Hubotは、HTTPインターフェースも備えています。これはデフォルトで8080ですが、PORTの環境変数を指定することで変更できます。

$ export PORT=9999

ファイヤーウォールの中にいる場合は、このポートで外からhubotにアクセスできるようにしておきましょう。
EC2の場合はセキュリティグループを確認しておきましょう。
そして、あなたのHubot HTTPインターフェースへのURLをSlackのHubot URLの欄に記入します。

Screen Shot 2014-07-08 at 11.23.14 PM

これで、SlackはHubotへのメッセージをこのHTTPインターフェースに送信するようになります。
さあ、Hubotを起動してみましょう。

$ ./bin/hubot --adapter slack

Screen Shot 2014-07-08 at 11.26.54 PM

成功です!
Enjoy ChatOps!

おサイフケータイをキャリア契約無しのAndroidスマホで利用する方法

どうも、食あたりで悶絶中のnoradaikoです。
気を紛らすためにブログを書きます。

おサイフケータイを使ってみたい

僕はiPhone 3GSの時代からずっとiPhoneなんですよね。
おサイフケータイやスマート決済というものが日本では普及していてとても便利なのに、全くその恩恵に与れないのは勿体ないと感じたのがきっかけです。
しかし、それだけのためにキャリアを2台分も契約するのはちょっとコストパフォーマンスが悪すぎる。

そこで、キャリア契約無しのAndroidスマホおサイフケータイを使おうと検討したところ、いろいろ注意点が分かったのでここにまとめたいと思います!

おサイフケータイ対応のスマホを選ぼう

HTC J One

Androidスマホは実に沢山の種類が出ていますが、中にはおサイフケータイに非対応のものがあるので注意が必要です。
例えば、GoogleのNexusは非対応です。

僕は、HTC J Oneを購入しました!2013年の夏モデルです。
ちなみに海外向けのHTC Oneは非対応です。あぶねえ!
キャリアはauで、SIM無しです。

モバイルSuicaはSIM無しでは使えない

ここで衝撃的な事実です。
モバイルSuicaは、専用アプリの起動時にSIMカードが入っているかどうかを確認する処理があります。
もし購入したスマホがSIM無しだった場合、アプリが起動後に即終了します。
つまり、利用にはSIMが必要なんですね。
ちなみに、nanacoや楽天Edy、WAONは正しく設定できました。

解約済SIMカードを購入しよう

au SIM Card

上述の通り、モバイルSuicaを使うために正規のSIMカードが必要です。
実際に差してみるまで確証がなかったのですが、SIMは解約済みのもので大丈夫みたいです。

SIMカードには2つの軸で種類があるので注意です。それは、サイズバージョンです。
購入したAndroidスマホの仕様欄をよく見て、どれが対応しているのか必ず確認しましょう。
HTC J Oneの場合は、下記のタイプでした。

au Micro ICカード(LTE)

詳しくは au ICカード(Wiki)を参照してください。
ちなみに僕はYahoo!オークションで購入しました。

電波が無くても大丈夫

無事モバイルSuicaを設定できたものの、一点気になる事があります。
それは、キャリア契約をしていないので当然通常はネットワーク切断の状態である事です。
ドキドキしながら改札にタッチしてみたところ、通れました!!

これは、NFCチップ間の通信で読み書きが完結しているためだと思います。
Android OSはもはや関係ないという事ですね。

チャージにはネット接続が必要

アプリはチャージする際にインターネット通信をしている様子。
なので、もし外でチャージが必要になったらその場でインターネット接続が必要になります。

iPhoneのテザリングでネット接続しよう

AndroidとiPhoneとのテザリング方法にはいくつかありますが、Bluetoothテザリングは出来ません。ペアリングが何度やっても失敗します。
ここではWi-Fiを使ったテザリングをしましょう。以下のページが参考になります。

iPhoneでインターネット共有設定が完了したら、Android側でWi-Fi接続の設定画面を開き、iPhone端末を選択しましょう。
あっさり繋がったと思います。

iPhoneはいつおサイフケータイに対応するのか

AppleはiBeacon推しのようですから、NFC搭載は微妙なところですね。
仮にNFCが搭載されたとしても、日本独自のおサイフケータイ規格には対応しない気がします。