なぜ CoffeeScript がダメか
自分は CoffeeScript が好きではない。個人的に書き捨てるコードを書くときには良いだろうけれど、継続的にメンテナンスが必要なコードに、この言語は絶対に採用してはならないと考えている。
CoffeeScript のメリット
CoffeeScript を採用することで発生するメリットについて、僕の認識を書く。当然、CoffeeScript というのが存在するためには、それ相応のメリットがあるはずだし、メリットの説明なしにデメリットとの差 (つまり採用すべきかを判定する基準) は導けないからだ。
箇条書きで
- タイプ数が減る
- function が -> になるのでカッコいい
- 括弧を書かなくてよいのでシンプル
- グローバル変数を使いにくくなるのでバグが出にくい
- == と != が使えないのでバグが出にくい
CoffeeScript のデメリット
- 単純な JS へのトランスレータ (革新的な機能は特にない)
- デバッグが難しくなる (ブラウザのサポートが必要)
- JS の知識がないと書けない
CoffeeScript は基本的には、シンプルに書きやすくすることにフォーカスされていて、例えば非同期処理が劇的に読みやすくなるとか、そういうことはない。function を -> って書けるとか、記号的な文法は書きやすくはなっても、そんなに読みやすくはならない。
確かに、CoffeeScript の導入によって、書きやすくなるコードは大変に多い。「JSではなぜこれができないんだ!」と思ったことが解消されて、かゆいところに手が届く。
しかし、継続的にメンテナンスが必要なコード (OSSとか、ウェブサービスのコードとか) というのは、書いている時間よりも、読む時間・読まれる時間のほうが多い。書くのは一人でも、読むのは複数人いるし、しばらく触っていないコードは、例えそれが自分で書いたコードであったとしても、また読解する必要がある。
CoffeeScript を読む場合、読む人には CoffeeScript の知識と、JavaScript の知識、どちらも必要だ。むしろ JavaScript を詳しく知っていなければ、CoffeeScript のメリットは理解できない。前述の通り、読む人は書く人よりも多い。書く人がいくら楽になっても、読む人にとって、CoffeeScript で書かれていることは単に学習コストの増大であり、メリットではない。
逆に、読む人にとってメリットがあれば、それは書く人にとってのメリットの何倍も嬉しいことになる。では CoffeeScript で書くことによって、JavaScript より読みやすくなるか、というと、そうでもない、と自分は思っている。function が -> になることで読みやすくなるか? 括弧を書かないと読みやすいのか? タブによるインデントの強制は読みやすさに貢献するかもしれないが、これは単にコーディングルールの問題だ。
バグが起きにくい仕組みは大変素晴しいものだけれど、残念ながらそれは、CoffeeScript を採用することで読む人にかける負担 (これは場合によって何倍にもなる) を上回らないと考えている。むしろそこは、JSLint などで、書く人が気をつける、すなわち負担をうけて解決すべきだと考える。
まとめ
将来 CoffeeScript に、使うと超読みやすくなるよマジやばい!!! っていう機能が入るといいと思いますが、そうでないなら、絶対に OSS とかをこれで書くのはおすすめできない。
CoffeeScript が現状のままだと、こんな未来が想像できます。
「うわ、これおれが CoffeeScript 期に書いたやつかよ。この言語オワコンって言われてから何年経ってんだ…… もう文法覚えてねーな。あ〜終わりゆく言語の文法を学びなおすのか……まじめげるな……」
✖
✖
FlashAir の HTTPD をエミュレーションするスクリプト
FlashAir に搭載されている HTTPD をエミュレーションする Plack::App::Emulate::FlashAir というのを書いた。SD カードマウントして書きかえて実機に直接アクセスするでもいいんだけど、それだと、書きこみで待たされたり、接続している間ネットができなかったりする。
機能は以下の通り
- ./sdcard/ を sdcard のルートディレクトリとする
- List.htm (コピーするのはアレっぽいので、付属のは自分で書いたやつ) によるディレクトリインデックス
- thumnail.cgi によるサムネイル画像取得 (実機と同じく exif の ThumbnailImage を展開しているだけ)
- command.cgi のダミーレスポンス
- config.cgi のダミーレスポンス
List.htm をリライト (デザインかえたいとか) するとか、別途機能をちょっとつけたいときのデバッグに便利だと思う。
あと、SDカード内のファイルを最新順に表示するページをつくった。
- https://github.com/cho45/flashair/blob/master/sdcard/recent.htm
- https://github.com/cho45/flashair/blob/master/sdcard/lib.js
を FlashAir のカード内のどっかにおいて、アクセスしたら動くとおもう。iPhone と Android でまぁまぁいい感じになるように調整した。
FlashAir
FlashAir というのが最近出たらしく、おもしろそうなので買ってみた。機能的には、Wi-Fi の AP と HTTPD として動いて、SD カード内の画像をダウンロードできる、というもので、Eye-Fi の競合 (機能的には違うんだけど) 的製品になっている。
Eye-Fi は持っていないのに、いきなりこんな謎なものを買ったのは、HTTPD が動いてくれるというところにひっかかったからだ。カメラみたいなデバイスで HTTPD が動くのはなんとなくわくわくするのである。
FlashAir は、割と素直な感じで、SD カードの中身をそのまま HTTPD で配信する感じなので、組み込みのページ以外に、自分で HTML と JS と CSS を書けば独自ページを作成できる。また、組み込みで配信されるページ自体も、SD カード内のファイルをいじると変更できるようになっている。ハードコードされていたりしないのは非常に嬉しいと思う。
ということで、SDカード内の写真のうち、最新順に表示するページを作ってみた。ファイルシステムの関係上ファイル名に制限がある (拡張子が3文字までとか) とか、thumbnail.cgi の挙動がおかしいとかあるけど、こういうのは簡単につくれた。今後ファームウェアアップデートで HTTPD がもうちょい安定するといいなあと思う。
なんとなく、スマフォのカメラの変わりに使えたらいいな、と思っていたけれど、ネットワークの関係でそうもいかない。FlashAir には AP として接続するため、その間、3G 回線など、Wi-Fi と排他的になっているネットワークが使用できない。FlashAir はもちろんインターネットには接続されないので、FlashAir に接続している間、スマフォはインターネットから切断されてしまう。picplz とかそういうアプリは、送信できない場合にキューに貯めるから、AP からの接続をきったあとにアップロードが開始されるだろうけれど、インターネットと同時に接続できないのは結構ストレスがあるので、用途によっては全く使えない感じになりそう。
あと Yahoo! トピックスに載ってた情報によると、SDK も配布されるみたいな話があるので、それはそれで楽しみです。
追記
関連エントリー
- ✖ PQI Air Card Wi-Fi内蔵SDカードアダプタ (アダプタのみモデル) 6W21-0000R1 cho45 pqi ★ 4.0 ...
- スマフォのテザリングを主回線にした家庭内LANの構築 cho45 ★ 5.0 / 5.0 cho45 結局これを買って、あとかなり昔に買ったしょぼいルーターを使って構築してみた。 インターネット...
- NanoVNA のリモート化 (Wi-Fi 中継) アンテナの調整をする場合、給電点 (測定点) と調整点は離れていることが多いなというコンテキストで、NanoVNA の Bluetooth ...
- IPv6 IPoE + DS-Lite 環境での RTX1200 の設定 ひょんなことから(?)RTX1200を譲ってもらったので使ってみる。VPN 貼りたいとかいう欲求はなくて、普通に家庭用ブロードバンドルーター...
- おうちのメインRaspberryPiの入れ替え メインの Raspi という存在が自宅にはあるのだが、だいぶ前にセットアップしていろいろ秘伝のタレのような状態になっていたうえに、ろくに a...
最近書いたなんとなくかっこいいかなと思うコード
JSDeferred のサンプルコードの殆どは、pre に書いてあるやつをそのままJSで実行する形になっている (二重に書いていない)
その中で console.log() とかを使っているけれど、デモなので console.log() をブラウザ側ではなく、ページ側に表示させたいと思い、それらの console.log をフックしている。この場合、評価したいコードは文字列として存在するので、Function オブジェクトを使って console のダミーを作って実行するようにした。
new Function('console', code)({ log : function () { ... } });Function オブジェクトの引数の名前を console にして、実行するときに代替オブジェクトを渡すようにした。すなわちこの場合 console はローカル変数になっている。
こうすることで、元々の console.log には一切手を加えず、このコードを実行している間だけ、console オブジェクトをさしかえた。一時的に大本の console.log を差し替えるやりかたは、非同期なコードがまざると大変なので、いい思い付きをした、と自画自賛しました。




