ぱろっと・すたじお

技術メモなどをまったりと / my site : http://parrot-studio.com/

「Rubyのしくみ」 "10.times do"から始まる冒険

お正月って、あらゆる気力を奪われる時期なわけですよ

長期休みって意味では夏休みも変わらないはずなのに、
世間の空気感も含めて、全力で怠惰になるというか、
ゲームをやる気力すら削がれるというかc(・ω・`c )っ

そのうち布団から出るのすら面倒になり、
布団の中で積んでいた漫画を崩した結果、読むものがなくなり、
ついに積んでいた技術書を崩し始める・・・そんな時期なのでございます

・・・というのがどこまで本当かはともかくとして、
お正月にだらだらと読んでいた本がこちらに(´・ω・)っ

Rubyのしくみ -Ruby Under a Microscope-

Rubyのしくみ -Ruby Under a Microscope-

Rubyist Magazine - 書籍紹介『Rubyのしくみ Ruby Under a Microscope』

「プログラム(言語)とは、結局のところメモリの書き換えである」と、
セガの方もおっしゃっていましたが・・・


「プログラミングを教える」ということ - ぱろっと・すたじお

・・・「言語がどのようにメモリを使っているか?」は、
言語を深く理解する上では重要な概念ですし、
少なくともパフォーマンスチューニングにおいては必須です*1

実際、新人時代からJavaを書いていたものの、
「感覚的に理解した」のはこちらの本を読んだときです

Java 謎+落とし穴 徹底解明 (標準プログラマーズライブラリ)

Java 謎+落とし穴 徹底解明 (標準プログラマーズライブラリ)

この本もJavaのメモリ管理について解説されており、
「参照」とは何なのか、GCは何をしているのかが理解できまして、
それ以降ぬるぽ*2を作り込むことが圧倒的に減りました( ゚д゚)o彡゚

その後、Javaを離れてRubyを書き始めたときも、
最初のうちはJavaっぽいコードを書いていたものの、
本質的にRubyっぽいコードに近づき始めたのは、こちらを読んだときです

Rubyソースコード完全解説
http://i.loveruby.net/ja/rhg/book/

この本・・・というかサイト(RHGと略すらしい)は有名でして、
Rubyを深く知りたい方はたいてい目を通しているはずですが、
どうにも解説しているバージョンが古い、という問題がありました(´-ω-)

その「RHGの現代版」と言えるのが先ほどの本でして、
本質的な狙いはほぼ同じです

とはいえ、私自身はC言語に明るいわけではなく、
Brainf**kの評価器を作れる程度の知識*3はあっても、
正直YARVの解説は難しすぎて、完全に理解することはできません(´・ω・`)

とはいえ、表面的にでも「何をしたいのか?」は読み取れますし、
5章以降のオブジェクトに始まる一連の話は、
C言語の細かい知識がなくても十分にわかります

Rubyにおいて全てがオブジェクト=メモリの束で管理されているなら、
オブジェクトの構造が理解できれば、Rubyの本質的な部分が、
かなりのレベルで見えてくるんじゃないかと(`・ω・´) *4

そもそもRuby自体(おそらくはLisp等と同じく)、
「概念」とか「理想」がまずあって、それを「実装」している感じで、
その「概念」自体はわりとシンプルで合理的なわけです*5

つまり、「何に使うか?」という「目的」ではなく、
「こういう言語にしたい」という「理想」が起点だと思っているので、
そのあたりの「意図」を読み取れれば、後は応用なのかな・・・と思います

逆に、「概念」や「理想」が先行しているからこそ、
JRubyやRubiniusのような他の処理系も存在できるわけで、
そのあたりの解説も面白いものになってます

「黒魔術」と言われがちなRubyが、
実際のところ「合理性の塊」であることがよくわかるという意味でも、
この本は面白いですし、おすすめします・・・が・・・


・・・やっぱり難しい本だと思います、ええ(´-ω-)

*1:メソッドの呼び出し」すらも、突き詰めればメモリ管理の問題です そのあたりの理解を助けるのに、平山さんの本はとても優れてます

*2: ガッ

*3: ネタプログラミング言語クリエイターYouma (Gunma.web #8) - ぱろっと・すたじお

*4: RHGを読んでいても、「Module#prepend」がどう実装されているのかはわからないのですが、この本を読むとすっきりします(`・ω・´) b

*5: 例:「全てはオブジェクトである」「(たとえ演算子であっても)全てはメソッド呼び出しである」etc...

「エンジニアでも恋がしたい」(・・・らしいが、いくらなんでも展開が早すぎるやろ)を解いた件

POH!も4回目ですってよ、奥様(`・ω・´)


マンガ版「エンジニアでも恋がしたい!」〜転職初日にぶつかった女の子が同僚だった件〜|paizaオンラインハッカソン4 Lite

今回は評価点の高低でストーリー分岐する仕組みだったわけですが、
過去3回に比べると、一番簡単な内容だったと思います
たぶん、1回目と同じくらいかもしれません


「女子大生とペアプロするだけの簡単なお仕事」でSSSをとるまでに考えたこと - ぱろっと・すたじお


「女子大生とペアプロ問題」の言語別通過率を分析してみる - ぱろっと・すたじお


天才火消しエンジニア霧島さんのトラップに引っかかった件 - ぱろっと・すたじお

今回は間口を広げるための回だったようで、
ITmedia等でも取り上げられました


プログラミングでストーリーが変わるぞ! Webマンガ「エンジニアでも恋がしたい!」公開 - ねとらぼ

今回の特徴は、3問連続で突破しないといけないところです

しかし、1問目2問目は足切り問題であり、
「職業プログラマがこれを即座に書けないとマジで話にならない」レベル*1で、
3問目の問題が本命です

とはいえ、3問目も100点が取れない場合にヒントが出るため、
その単語でググってアルゴリズムを押さえれば解けてしまいますがΣ(゚Д゚)ガーン

ポイントは「O(mn)」の計算量を、いかにして「O(n)」にするか・・・なのですが、
アルゴリズム自体はすぐ出てくるわけで、
後はどう効率的なコードにするか、だけでしょう*2

今回は簡単なため、私の解答は「続きを読む」に貼っておきます
ぜひ自力で解いてみてください


・・・なお、どうでもいいことですが、
個人的には100点の水着より60点の浴衣の方が好みですΣ(・ω・ノ)ノ



<追記>
CoffeeScriptでも書いてみたのですが、
3問目のTestCase4でエラーになりますΣ(゚Д゚)ガーン

配列のindexが間違っているのかと思って、
デバッグ文とか突っ込んだりしてみたのですが・・・
アルゴリズムは全く同じなんですけどね

*1: それこそ、面接でこれを書いてくださいと言われてもおかしくないレベル

*2: 実際、名前そのものは知らなくても、よく使うアルゴリズムだとは思います というか、使ってたのにな・・・(´-ω-)

続きを読む

今さらOGPとTwitterCardについて調べてみた

Facebookのような「THE・リア充空間」に全く縁のない私ですが、
最近になってやっと「Open Graph protocol」(OGP)というものの存在を知りました


The Open Graph protocol

最近はてなにRO(+α)のBlogを移転して気づいたのですが、
URLを貼り付ける際に開く選択で、「埋め込み形式」ってのがあります

例えばこんな感じで(´・ω・)っ


新しいスマフォゲーを試そう・その1 - あるネットゲーマーの日常

当然、この方が見栄えがいいし、
この形式が並んでいる中に非対応のサイトがあると、
浮いて見えたり目立たなかったりするわけです
(ゲームのBlogで画像多めなので余計に)

なので、「埋め込みが可能になる条件」を調べていて、
たどり着いたのがOGPだった・・・というわけです


「ブログカード」をOGPなどに対応しました。さまざまなWebページをコンパクトに整形して掲載できます - はてなブログ開発ブログ

これを見ると、まだ対応して数ヶ月ってレベルだったんですね・・・
Blog移転が10月だったので、いいタイミングでした(`・ω・´) b

さて、私が最近作っているサイトに、
「チェンクロパーティーシミュレーター」というものがあるのですが、
これもOGPに対応させてみました


Get our light! - チェンクロパーティーシミュレーター

自分のBlogで紹介する際、埋もれてしまうのが気になったので・・・(´-ω-)

とはいえ、対応そのものはタグの追加だけなので楽です

<meta property="og:site_name" content=“サイトの名前" />
<meta property="og:title" content="記事タイトル" />
<meta property="og:type" content="website" />
<meta property="og:image" content="記事画像" />
<meta property="og:url" content=“記事のURL" />
<meta property="og:description" content="記事の概要" />

https://github.com/parrot-studio/cc-pt-viewer/blob/master/app/views/layouts/application.html.erb

今回は1ページしかないので適当に書きましたが、BlogなどのCMSでは、
自動でこのあたりのタグを生成する仕組みにすればいいわけです

・・・と、これだけでも十分だったのですが、
はてなBlogにTweetを貼り付けたところ、このように見えました

post内容の下にBlogの概要が表示されています

おそらくOGPが絡んでいるのだろうと、自分のサイトをpostしてみても、
このようには見えなかったので、調べてみました


Twitterカード | Twitter Developers

このように、タグを追加して「申請」しないとダメだそうで(´-ω-)

とはいえ、OGPに対応しておけば、追加するタグはシンプルです

<meta name="twitter:site" content="@parrot_studio">
<meta name="twitter:card" content="summary">

これだけΣ(゚Д゚)ガーン

申請も面倒なのかな・・・と思ったら、わりと簡単でした
(ただし、反映されるまでに少々時間がかかります)


Twitter Cards利用申請 - Qiita

するとこのようになります

これだけで「できるサイト」っぽくなって素敵ですね(`・ω・´)


最近、(いいか悪いかは別として)ニュースをまとめるサイト・アプリが増えていますが、
そこで「埋もれないために」、このような仕組みに対応することも必要かと思います

例えば、私がよく見ているMSNのニュースサイトはこのようなデザインです

http://www.msn.com/ja-jp/news

少なくともOGPに対応していない限り、
「画像付きの見出し」にはならないはずです

これに気づいただけでも、
はてなBlogに移行した価値があったかな・・・と思ってます



むしろ問題は、「この(技術っぽい)Blog」と「RO(+α)のBlog」、
どっちが「私にとってのメインBlogか?」ってことで・・・Σ(・ω・ノ)ノ

もう一度Nginx+Unicorn+Railsを試してみる

もう3年以上前のことですが、一度Unicornを試してはいます


Rails3アプリをnginx+unicornで動かしたら速すぎた - ぱろっと・すたじお

その頃はまだ「運用」に関するノウハウが足りておらず、
サーバ再起動のたびに失敗する起動スクリプト*1を手動で実行するとか、
速さの代償にいろいろ面倒を背負い込んでいる感じでした(´-ω-)

なにより、動かしていたサイト自体が頓挫し、
その後構築していたRO用のシステム*2は、
一つのサーバに複数動かす仕組みだったので、あまりUnicorn向きではありませんでした

(今の仕事でも、Rack以外の部分も含めて統一した運用をしたいということで、
 あえてApache+Passengerという環境で動かしています)

そして今取り組んでいるのがこちらですが・・・


Get our light! - チェンクロパーティーシミュレーター

・・・これを独立したドメインにするか悩んでいて、
とりあえずサーバだけ移行しようかな・・・と考えていたところ、
今月のWEB+DBでRackサーバの記事を読んだわけです*3

WEB+DB PRESS Vol.83

WEB+DB PRESS Vol.83

一つのサーバに一つのアプリならUnicornで問題ないですし、
記事の中でもだいぶ枯れていると紹介されていたので、
いい機会だからやり直してみようかと


以上、経緯と前置きでしたΣ(・ω・ノ)ノ


なお、今回参考にさせていただいたサイトはこちらです

Ruby - Nginx+Unicorn設定ファイルサンプル - Qiita

Unicorn+Rails入門 - Less is Best

Unicornの設定

Unicorn側は3年前とそんなに変わるところがないのですが、
同一サーバの場合はソケットがいいらしいので、
そこが以前と変わったところでしょうか

https://github.com/parrot-studio/cc-pt-viewer/blob/master/config/unicorn.rb

といっても、以前のシステムはソースをGitHubに置いてない*4ので、
比較しようもないわけですが・・・(´・ω・`)

あと、以前は「unicorn_rails」ってコマンドを使っていましたが、
今はただの「unicorn」で起動するのが主流だそうです

Nginxの構築

Passengerの場合、組み込む都合で専用のインストーラーがあったりしますが、
今回はProxy経由なので普通にyumでインストールしただけです

設定ファイルもひな形を作ってくれるツールがあります

https://github.com/i2bskn/nginx_utils

Unicornとの連係を前提にしたconfを出力できるので、
そこだけ指定した形で出力し、細かいところは後からいじりました

upstream backend-unicorn {
  server unix:/path/to/app/tmp/sockets/unicorn.sock;
}
server {
  listen 80;
  server_name ccpts.parrot-studio.com;
  root /path/to/web/root;
  index index.html;
  location / {
    try_files $uri @proxy;
  }
  location @proxy {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://backend-unicorn;
  }
}

「ファイルがあればそのまま返し、なければProxy」って設定が、
これだけ簡単に書けるのはすばらしいですね(`・ω・´) b

まあ、以前からあったのを、当時の私が知らなかっただけ、という可能性も・・・

あとは自動起動スクリプト(for CentOS6.5)ですが、
調べるといろいろ出てきますので、必要なところを書き換えて使用しました
私がやったのは、「unicorn_rails」を「unicorn」に変えた程度です

運用レベルでのPassengerとの違い

PassengerはNginxに組み込まれて動いており、
アプリ再起動のために「restart.txt」の仕組みが存在します
なので、基本的にはアプリの管理を一般ユーザで実行できます

Unicornの場合はアプリ自体をinit.dで自動起動しているため、
実行権限はrootになります
そのため、システムが生成するtmp以下のファイルは、root権限になります

このため、アプリのcacheクリア等*5をsudo経由でやらないといけないのが面倒なのですが、
一般権限でUnicornを動かすような指定も面倒だったので、そこは許容してますΣ(・ω・ノ)ノ

いやまあ、「最近のサーバ管理手法」とかなんとかいろいろあるのはわかりますが、
今回の目的は「Nginx+Unicornで動かすこと」なので、
その辺は "面倒になったら" 考えます


以上、わかっている方には当たり前の話でしたが、
例によって自分用のメモ書きということで...φ(・ω・`)

*1: 今にして思えば、スクリプトの実行順の問題ではないかと思いますが、もう環境を破棄してしまったので・・・

*2: http://parrot.hatenadiary.jp/entry/2014/04/16/124949

*3: 実際には電子書籍版ですが・・・

*4: あまりにソースが汚い&機密情報の切り出しが甘い

*5: 今回のシステムの運用上、memcachedよりファイルキャッシュが楽なのです

例えば、パスワードを避ける

今回も長いメモ書きなのですが・・・

最近、パスワードに関する議論*1が多かったわけですが、
もっと根本的にどうにかならないのかな・・・と思いまして

自分でそう思ったというか、せんせー*2Tweetを見ていて、
「もう一つ上のレイヤーで考えないといけないんだな・・・」と気づいたというか

つまり、こういうことなのかなとΣ(・ω・ノ)ノ

考察の前提

この手の考察はいくらでも発散するので、大前提として、
「不特定多数に公開されたWebシステムにログインする場合」に限定します

「パスワード」の限界

極論ではありますが、「文字列のみで照合する」という仕組みである以上、
どうやったって「いつかは」突破されるわけです

そもそも、「辞書に載ってない文字列」というのは、
「人が覚えるのに適していない文字列」なので、面倒ですよね(´-ω-)

「認証」が満たすべき要件

私自身、実験的に「合い言葉(=マルチバイト文字列)認証」のシステムを作ったことがあります


下書きをひっそりと共有するサイト「紙片」を公開しました - ぱろっと・すたじお

この問題点を今改めて考えてみると、
「意味的な表現とバイナリ表現が一致するとは限らない」ってことで

つまり、「UTF-8で"ああああ"」くらいであれば、
ほとんどのブラウザで一致するはずです

しかし、絵文字のような最近定義された文字列を使われた場合とか、
そもそも日本語がまともに実装されてないブラウザ*3の場合、
そこは保証できません(´-ω-)

一方、ASCIIの範囲であれば、たいていのシステムでコードが一致するため、
「意味とバイナリ」が1対1で対応するはずです
そういった利点もあったのかな・・・と

なにより、こういった「自身が設定した"何か"による認証」は、
「それを記憶しておかなければならない」というコストが常に存在するわけです

つまり、「何も覚えてなくていい」状態が理想なのではと

デバイスの依存性と二段階認証

「覚える情報を減らす仕組み」として、
現時点で最適な回答としては「パスワードマネージャー」でしょう
実際、私も"ほぼ"移行しています

パスワードマネージャーの問題はシンプルで、
「パスワードマネージャーが使えない環境では結局手打ち」ということです

例えば、Twitterのパスワードをソフトウェア的に管理していたとしても、
Androidのクライアントアプリにログインするときは、
キーボード入力しないといけません

その辺の解決策として、iOS8版1Passwordは良くできていると思います

それでも、「アプリ側が仕組みに対応していないと使えない」*4だけでなく、
そもそも「iOS8以上のデバイスでしか使えない仕組み」であり、
Androidはもちろん、私のiPad miniはiOS7なので、iOS系なのに使えないわけです(´-ω-)


「パスワードを使い回したとしても、一定の効果がある手段」として、
最近では「OTPトークンによる認証」や「二段階認証」が存在します

OTPトークンはオンラインRPGのログインでもよく使われていますが、
1分ごとにアルゴリズムで値が変更されるため、
たとえある時点での値が漏れても、ログインは相当難しくなります

欠点はシンプルで、「OTPトークンがない限りログイン不可」ということです

スマフォにOTPトークンアプリを入れることである程度リスクを軽減はできますが、
OSのアップデートで動かなくなるとかよくあるので、
たいていは物理的トークンの方が楽、という結論に至ります(´・ω・`)

やはり、現時点で妥当なのは「二段階認証」でしょう。

GoogleやMSにログインする場合、IDとパスワードが正しくても、
送られてくるSMSやメールに書かれたコードがなければ、
最終的なログインはできません

OTPトークン方式を実装しているROでも、
トークンを設定してない場合、「電話による認証」が行われます

ログインすると「あちら」から電話がかかってきて、
コードが「音声で」読み上げられるので、
それを「Web画面に」入力するわけです

冷静に考えると、この方式はかなり「楽」で、
OTPトークンと電話、どちらを忘れる確率が高いかは自明ですし、
「OSのアップデートで電話ができない」ってことはまずないはずです*5

デメリットは、「(一時的とはいえ)電話番号を渡す」という心理的障壁と、
あと導入側の料金的コスト*6が、おそらくOTPより高いという点でしょうか

そして、あまりないことかもしれませんが、
「電話がない場合はどうしようもない」という問題もあります

とはいえ、最近は「スマフォでインターネット」が一般化しており、
「ネット環境はあるけど電話番号がない」というケースはだいぶ減っています

ですが、格安SIMでのSMS機能はまだまだ「オプション」扱いであり、
全くないとも言い切れません(´-ω-)

「パスワードの代わり」を「ユーザが選択する」

「年に一度ログインするかわからないレベルのサイト」で、
私が実際にやっていることなのですが、
「あえてめちゃくちゃなパスワードを登録し、ログインの都度リセットする」という手段があります

つまり、パスワードを覚えることを放棄しているわけですが、
冷静に考えれば、これは二段階認証の二段階目と同じようなものであり、
ならば「二段階目のみ」にはできないものでしょうか?

どうせGoogleでもMSでも、ログインしたブラウザでCookieが生きている限り、
再度の(二段階)認証を要求してこないわけですし、
「自分が設定したパスワード(のようなもの)」は必要なのでしょうか(´・ω・)?

・・・ということを先日の朝考えていたら、
夕方にこのようなものが流れてきました


Passwordless - A node.js/express module for token-based logins

Passwords are broken. Inspired by Justin Balthrop's article Passwords are Obsolete token-based one-time password (OTPW) authentication is faster to deploy, better for your users, and more secure.

https://passwordless.net/


この仕組みのポイントは、認証コードの送り先を任意に選択できる、というところです

Flexible

Deliver your tokens via email, text messages (SMS), or smoke signs. You can embed Sendgrid, emailjs, Twilio, or any other framework you like to get the token to your user.

https://passwordless.net/

つまり、この仕組みを使えば、実装によっては
「ユーザがコードの受け取り先を選択する」ということが可能になります

つまり、「今日は電話を忘れちゃったけど、メールなら使える」という場合に、
メールでコードを送ってもらう、ということが可能になりそうです(`・ω・´)

このフレームワークはnode.jsによるものですが、
同じ仕組みは他の言語でも可能なはずで、
今後こういった仕組みがどんどん出てくるかもしれません

問題点は・・・?

論理的に考えると、「パスワードを捨てる」というのは妥当に見えます

一方で、「パスワードで認証する」というのは「当たり前」であり、
「説明がいらない」という利点もあります

都度メールでコードが送られてくるのは「面倒」なので、
まだパスワードを入れる方が楽だし、もっといえばIDだけでログインできてもいい

こういう層には響きません(´・ω・`)

実際、初期のLINEでは、
パスワードの存在そのものを認識してないユーザが多数いたようです


「LINEのパスワードを忘れた」「ログインできない」が急増している理由とその対策 | LINEの仕組み

特に、最近のスマフォゲーでは、「ユーザ登録が不要」なのが常識*7であり、
「端末移行するための簡易パスワード」くらいなので、
「ログインしている」という認識は薄いと思われます

もちろん、「アプリとWebサイトでは違う」のですが、
今は「Webサイトがあってもアプリからアクセスする」のが一般化しており、
果たして「面倒な仕組み」が受け入れられるのか・・・というのは問題かと

このあたりは「時代の流れ」で決まるもので、
「それが当たり前」になるまでには時間がかかるわけですが、
今ですら、「二段階認証」の存在を認識してないユーザが多いわけですしね・・・

他にも、「仕組み的な穴」もまだあるはずで、
このあたりの議論を進めてもらえると、
「目指すべき方向性」が見えるのかな・・・と思います*8

おまけ:「Digits」に対する疑問点

そして今日、Twitterが新しい認証の仕組みを発表しました


Twitter、モバイルアプリ向け新SDK「Fabric」発表 パスワード不要の次世代認証「Digits」リリース - ITmedia ニュース


電話番号確認方式のユーザ認証をTwitterがデベロッパサービス(一種のAPIスイート)Digitsとして提供 - TechCrunch

これが「ログインのたびに都度電話番号を入れる仕組み」ならパーフェクトだったのですが、
ざっと読んだ限りではLINEと同じような仕組みであり、
「電話番号が変わったらどうするのか?」とか、同じ問題を抱えているようにも見えます

電話帳をUPして結びつける機能もあるようなので、
「以前その番号を使っていた人の知り合いがレコメンドされる」・・・という、
LINEで発生していた問題もあるのではないかと

このあたりは情報がもっと出てこないとなんとも言えないのですが、
さすがにTwitterならそこはクリアできている、
あるいはしてくれると思ってます(`・ω・´)

追記

書き終わってからこのような記事を見つけました


Windows 10はセキュリティキー不要の2段階認証機能搭載に - ITmedia ニュース

まだ詳細はわかりませんが、認証の安全性と利便性を、
どうにかして両立させたいんだな・・・という感じはします

ついでに、Googleの取り組みも(´・ω・)っ


Google、USB使った2段階認証サービスを提供 - ITmedia エンタープライズ

こっちは特定のデバイスが必要という意味でOTPトークンに近いですね
おそらく企業向けを想定しているのかもしれません

*1: ・・・か、どうかについては個々で判断していただいて・・・

*2: と、私が表記する場合は、この分野におけるラスボスである「あのお方」でございます

*3: 現状ほとんどないとは思いますが、今後ありえそうなのは例えばIoT系デバイスの簡易ブラウザとか

*4: これは時間が解決しますが

*5: おっと、アップデートで通信ができなくなった某OSの話はそこまでだ( ゚Д゚)y─~~

*6: 参考までに、Twilioの料金体系 http://twilio.kddi-web.com/price/

*7: 実際、私も「特定サービスへのユーザ登録を要求するゲーム」はその時点で(内容に興味があっても)蹴ってます

*8: 「筋の良い方々」の思考リソースは、こういう方面に使ってほしいのですよ・・・(´・ω・`)