QiitaにJavaScriptについての記事を投稿しました。
http://qiita.com/derui@github/items/6e8de68cc1b7295de3a6
なんか最近、Javascriptを書いていると、なんかこれどっかで見たことあるなー、という感覚を覚えていました。ソースは忘れましたが、JavaScriptはLispを作りたかった人が作った言語、という話を目にして、そうか!と目から鱗が落ちた気分でした。
そんな気分を記事にしたものです。正確性は置いておいて、JavaScriptしかやらない人でも、Lispとか他の言語を学ぶことで、楽に概念を理解できる、ということもあるんじゃないかなー、と思いました。まぁ動的言語でLispになくて他の言語にある、なんてものはほとんど無いとは思いますので、Lisp一回学んでおくと、現在のプログラミング言語の概念は大体理解できちゃうんじゃないでしょうか。
PolymerのCSSについての記事を書きました
Polymerを利用して要素を作成していっていますが、CSSの書き換えルールとかが今一つよくわからなかったので、実際に簡単なサンプルを作成してみた記事です。うーん、完全に宣伝記事ですね。もうちょっと実のある記事をこっちにも書きたいのですが・・・。
PolymerでのCSSについて
http://qiita.com/derui@github/items/f23d840b787d1d72ae3a
今週のお題「テスト」
こういうのがあるのは結構前から知ってましたが、今回初めてこういうものを書きます。
昔のテスト
昔でテストというと、当然ながら学生時代のテストになるわけですが。今から思い起こすと、学生時代って試験多かったなぁ、という感じがします。特に高校では三年の後半は週に一回は模擬試験やってたような。私が学生時代は、ちょうどゆとり教育との境目(翌年度くらいから本格的に開始)だったので、土日は完全に休みでした。休み万歳。
そういう意味だと、今の学生はさらにテストが多いんでしょうか。それはそれで大変そうですが・・・。
テストというとテスト勉強、ということになりそうですが、年を経るにつけてどんどんしなくなった記憶があります。それに伴って成績が見事に落ちていったのもよく覚えています。特に古文。なんで古文で赤点と取るのかわからん、と教科の担任に言われて笑って誤魔化したことがあります。
学生時代のテストで一番覚えているのは、ちょうどテスト当日に39℃の熱が出て、しかし入学して一発目の中間試験だったということもあり、それでもテストを受けたことですね。結果はそれなりだったのですが、とにかく試験中が辛かったです。
今のテスト
さて、社会人になってからのテストは、IT業界の人間にとってはおなじみな方のテストを意味するようになりました。中間試験とかよりもこっちの方がよっぽど恐ろしいときも多いです。事前準備とか洒落にならないくらい大変な時の方が多いですし。
それと、TDDもそうですね。最近はこっちの推進みたいなこともやろうとしていますが、どちらにせよ、テストに正解というものが無く、常に思考しつづけないとならない、という点で、学生時代のテストとは一線を画していると思います。いつになったらこのテストをちゃんと書けるようになるのかと思いながら今日もテストを書き、そのテストを楽に書くための機構を作っています。
書いてみて
特に学生時代のテストについて、特に思い入れとかなんもないなー、と。思い返してみても、どうにもテストにいい思い出もなければよい思い出もないですね。むしろ社会人になってからのテストの方が色々とあって・・・。テストはもうちょっと平穏に進めたいものです。
以上、今週のお題でした。
Polymerを使ってみた、という記事を書きました
最近いろいろな事情があって、Qiitaに書くようになっていくと思いますが、とりあえず書きました。後日曜の停電からネットが繋がらなくてマジつらい。
http://qiita.com/derui@github/items/bafc8f68c55e0c9d8b70
内容としては、Polymerを実際に使うにあたって解決しておいたほうがいい問題とかです。まだ使い始めたばかりなので、これからどれくらいいろいろあるかがわかりませんが、とりあえず、といった感じです。
Sencha Touch2をTypeScriptでちょっと書いてみた。
気付いたら本気で一年の半分が過ぎそうです。最近時間の流れの早さが確実に早くなってきているのを実感しているので、もうちょっと週末のだらけっぷりをなんとかせんとなー、と思うこの頃です。
ところで、諸事情がありましてSencha Touch2をTypeScriptでちょこっと書いてみたので、その感想をばと思います。
Sencha Touch(というかExtjs)はTypeScriptには向かない
量は少ないのですが、ちょこっと書いてみたかぎりでは、ぶっちゃけこれ以上の感想があまり浮かばないというか・・・。
- TypeScriptのモジュールとかClassとかが基本使えない
- 型定義ファイル
- ExtJS自体が巨大なので、公開されているファイルをありがたく使わせてもらってますが、あまり効果が実感できないというか・・・。
- オブジェクトを超多用
- オブジェクトを書く分には、TypeScriptもJavaScriptも変わらないので、正直特に変わりません。
- それぞれのxtypeに対応する型定義はあるのですが、結局渡しているのはただのオブジェクトなので、毎回<...>でオブジェクトを静的キャストしてやらないと、補完とかもまったく効きません。なんということでしょう。
- クラスの定義とかで() => {}が諸事情で使えない
- () => {}は普通に使う分には便利ですが、クラス定義の時に使ってしまうと、windowとかそのあたりをthisとしてしまうため、結局JavaScriptで書いているのと変わらないという・・・。
な感じで、本来TypeScriptで重要なファクターとなる点がかなりの割合で潰されてしまっているため、TypeScriptを書くよりかは普通にJavaScriptを書いた方が、コンパイルとか無視できる分むしろ早くなるんでは?という例になりそうです。
CoffeeScriptの方がいいかも
オブジェクトを多用する書き方なので、あまりインデントでブロックを表記するやりかたは好みではないのですが、CoffeeScriptの方が楽に書けるような気がします。関数の書き方としても、TypeScriptの()=>{}が(大抵)使えないのに対して、CoffeeScriptの場合は常に() -> が使えるので、毎回functionを書きたくないからTypeScriptを使ってるのに結局functionを打ちまくる、というなんともな状況は回避できます。
CoffeeScriptを使った場合、TypeScriptで得られる利点(型定義によるコンパイルエラーとか)は得られませんが、その分早く書ける(はず)なので、テストを厚めに書く、というまさにRuby的な形でやることができるんではないでしょうか。
つまるところ
TypeScriptはJavaScriptを型定義を通して、固く使うことができる、ということが基本的な利点だと思います。しかし、JavaScriptの利点である柔軟性を十全に生かしたプロダクトで、しかもExtJSレベルで仕組みが構築されてしまっていると、TypeScriptを使うことによる利点が、TypeScriptの利点を享受するための作業によるコストを下回ってしまうのではないかと懸念しています。
ここはあれですね。TypeScriptでExtJSを書き直せばきっと誰かが幸せになれるんだと思います。そうなったら既存のExtJSとは似てもにつかないものになるだけでしょうが。
JavaScriptはfunctionを短く書く方法と、関数とグローバル以外の変数スコープができるだけで大分使いやすくなると、改めて感じた今日この頃でした。
Martiniでstatic fileが返せない
諸事情で、ちょっとサンプル的なプロジェクトを作成しており、利用するフレームワークとかアーキテクチャは自分で利用できるので、今回初めてGolangでのWebアプリケーション実装をやってみています。
フレームワークとしては
- Revel
- Martini
- BeeGo
などがメジャーどころのようですが、今回はフルスタックを利用するまでもないだろう、ということで Martiniを選択しました。Sinatraライクということで、それなりにとっつきやすそう、というのポイントでした。
静的ファイルが取れない
とりあえずHello, Worldを実行して、実際にファイルを配置して試しに表示してみようとしたところ、
[martini] listening on :3000 (development) [martini] Started GET /public/css/main.css for [::1]:46776 [martini] Completed 404 Not Found in 245.092us
みたいなエラーが山程出てきました。言うまでもなく、/public/css/main.cssは静的ファイルです。とりあえず、なんでかは知りませんが、Martiniがこれを普通のリクエストと勘違いして、んなHandlerはねぇ!と言っているのはわかります。
ですが、公式ページにちゃんと?こう書いてあります。
Serving Static Files A martini.Classic() instance automatically serves static files from the "public" directory in the root of your server. You can serve from more directories by adding more martini.Static handlers.
サーバーのrootにあるpublicディレクトリへのアクセスは静的ファイルへのアクセスである、とデフォルトでやってあるようです。
原因
まさかこんなところで引っ掛かると思ってなかったでちょっと焦りましたが、martini/static.goにログを追加して確認してみたところ、public/public/... のようなファイルを見るような感じになっていることがわかりました。これが原因でした。
martiniを使っているときに、CSSとかJsとかを読み込むときは、public/からの相対パスを絶対パスとしてアクセスするのがわかりやすいかと思いました。
(public/css/main.cssだったら、/css/main.cssとやる)
しかし、こんなところでひっかかる奴もいないのか、検索しても情報が出てこないのは焦りました。Martiniはかなりスモールなので、ソースを読むのがそんなに苦にならないのが助かりました。
レガシーな環境にBackbone.jsを導入したので振り返ってみる
Legacyという言葉が情緒溢れる言葉と聞こえなくなって久しいです。というかレガシー = COBOLという脳内変換が・・・。いかんいかん。
今いるプロジェクトも気が付いたら1年が過ぎてしまっていました。時間の流れが速すぎる、なんということでしょう・・・と言っていても時間は戻ってこないですね。でもたまには振り返る時間も必要じゃないかと思います。レガシーなプロジェクトを弄っている場合は特に。
今回は、レガシーなJavaScriptが蔓延るプロジェクトにBackbone.jsを導入し、現在までの評価をしたいと思います。もちろん私の目線限定です。
プロジェクトに入ったばかり
ほとんどJavaScriptを触ったことがない自分でもわかるほど混沌とした、そして大量のJavaScriptでした。詳しく計測していませんが、少なくとも5桁と6桁の間1/3程度はあったのではないかと思います。
どんな感じかというと
- グローバルばりばりだぜヒャッハー!
- jQueryでゴリゴリゴリゴリ
- DOMの位置関係でselectorをゴリゴリゴリゴリ
- ちょっとでも弄るとすぐ破綻・・・
- モジュール?何それおいしいの?
- jspのel expressionがそこらじゅうにあるんですけど・・・
- テンプレート?そんなものよりDOMコピーした方が早いでしょ?
- 限度ってあると思うんだ。
- 欠片もコメントが無いよくわからないけど大事な関数
- コメント過多で読みづらい関数
- つまりは可読性がかなり悪い。
- 他にも色々・・・
という感じが延々と続いていました。一見さんお断りってこういうのを言うんだ・・・って思わず思ってしまうくらい、動きを追うことができませんでした。
ちなみに環境はjQuery 1.4.4でした。当時すでに1.9とか1.10とか2.0が出ていた時だったので、ぉぅ・・・って感じでした。
入ったばかりのときはまず構造を把握するまでに時間がかかるのと、下手にいじるとまったく動かないとかを経験しました。
アーキテクチャを自由に決められるようになったころ
大体4ヶ月くらいで、アーキテクチャを自分の自由に決められるようになりました。なので、まずはちゃんとしたユーティリティとして underscore.js を導入しました。
そして、jQuery 1.5以降しか利用したことが無い方は信じられないかもしれませんが、jQuery1.4.4ではDeferred/Promiseが無く、すべてコールバックで書く必要がありました。4重になったコールバックとか可読性も何もありませんね。
また、jQuery をバージョンアップしたくても、全画面・全機能のテストが必要ということで見送られつづけていたので、少しでも混沌と戦うために、 JSDeferredを導入しました。JSDeferredにしたのは、特に依存が無い、ということと安定していそうということで選択しました。
$.ajaxをJSDeferredを利用した実装でラップして、Deferredが利用できるようになったことと、underscore.jsでユーティリティの心配をしなくてよくなったことで、少しだけ心の平安を得ました。
が、この時点で一つ問題が。
Deferredを理解してもらえなかった
その当時入ったばかりのメンバーに、コールバックではなくDeferredで書いてほしい、と頼んだら?という顔をされました。説明とJSDeferredのサンプルコードを見てもらっても?の状態のままでした。
仕方無いので、習うより慣れろ、の精神でやってもらうことにしました。もちろんサポートありで。ライブラリとかを導入するときは、メンバーの学習負荷を考えなければならない、と初めて実感しました。
Backbone.jsに憧れて
このプロジェクトは保守しながら、ガンガンいこうぜな開発を進める、という感じだったのと、どんどん画面側の改善要求が来るようになってきて、もう個人的にはどうしようもない状態(カオスを増やさないように実装する労力 < 作り直す労力)と感じてしまいました。
クライアントサイドMVCが声高に叫ばれてしばらく経っていた時分だったので、ちょっと検討しましたが、色々な理由でBackbone.jsを使うことに決めました。
- Angular.js
- マジで全部作り直すことになる。そんな工数出してもらえるわけがない。というか無理。
- Knockout.js
- 同上。
- Backbone.js
- とりあえずでも導入できそう。
が、この時点でまた問題が。レガシーなライブラリを利用している問題からですが、Backbone.jsはjQuery1.6以上を必要としています。それに対して1.4.4を利用していたため、ぐぬぬ・・・、となりながら一先ずあきらめて、Backbone.jsとほぼ同じAPIと動作をするようにしながら、ただし機能が足りない、とりあえずの似非Backbone.jsを作成して、それを利用して画面を作成するようにしてみました。
似非でも疑似でも、やはり秩序がもちこまれることで、作るのは結構楽になりました。
Backbone.jsを導入(ただし危険な橋を渡って)
似非ライブラリを少しずつ拡充しながら、Backbone.jsを導入できる機会を伺っていたところ、あるメイン画面を全面的に再構築するチャンスが到来しました。このタイミングを逃してなるものかと、Backbone.jsと、ついでにRequire.jsの導入を私の独断で決定。
グローバル変数と関数がからみあう既存部分を直すのはかなり骨だったのと、Require.jsを利用するのがプライベートでも仕事でも初めて(ぉぃ)だったので、調べものにもかなり時間を使いましたが、それでも無事に作成できました。
初めてながら結構な量を書いたので、Backbone.jsの勘所というのが少し理解した感じでした。
ただ、Backbone.jsに必要なjQueryのバージョンは相変わらず1.4.4なので、Backbone.jsのソースを読んで、1.6以上に依存している部分を、1.4.4でも利用できるメソッドで置き換えたバージョンにして利用しています。何か起こったらと思うと・・・。
Backbone.jsの使い方がわからないと言われた
Backbone.jsは公式ページがちゃんとしているので、読めば使い方とかがわかるー・・・と思っていたら甘かったです。読んでもやっぱりわからない、ということでそれなりの時間をメンバーのサポートに割く必要がありました。
そのときは時間に本気で余裕が無かったのであれですが、余裕があったのであれば、ちゃんと概念とか使い方をメンバーで共有する必要があるなぁ、と初めて実感しました。
色々導入
Backbone.jsとRequire.jsを導入したのを皮切りに、相変わらず独断で色々と追加したりで環境が大分変わりました。現在までと入った当時とで見比べてみるとこんな感じです。
Before
- すべてPure JavaScript
- jQuery、jQuery UI以外は自作プラグインくらいしかなかった。
- 自作プラグインもかなりヤバい作りだった。
- モジュールの概念なんて無い
- テストも無い、なんらかの自動化とかも無い
After
- Gruntを導入(これは私ではなくて前任者が最後にやっていきました)
- GruntでRequire.jsをコンパイルするように
- Sassの導入
- 全面的にScssで書き換えた状態まできました。
- GruntでSassのコンパイル
- Bowerの導入
- Karmaの導入 + ユニットテストを一部作成
- underscore.jsのtemplateを管理しやすくするJSTを導入
- JSTのコンパイルもGruntで行うように
- jQuery以外にも色々と導入
- spin.jsとかも。
- Gruntからビルド・デプロイまで一通りおこなえるように。
JavaScript関連だけでとりあえずこれくらい変わりました。それなりに快適になったとは思います。また、これ以外にもGradleを導入したり、Eclipse以外からちゃんとビルドできなかったのを、Maven単体でも動作するようにしたり、CIサーバーを立てたり、Gitlabを導入したり、と結構いろいろとやっています
Backbone.jsをしばらく触ってみて
シンプルかつ軽量なのは非常に美徳だと思うのですが、Backbone.jsはとにかく基本部分しか無いので、
- 同じような記述がそこら中にある
- オレオレ実装をしようにも時間がかかるのでとりあえずな実装で逃げる
とかが目立つようになってきました。今のところほとんど私がBackbone.jsの周りをいじっていて、他のメンバーが大規模に触る、ということはまだないのでいいですが、他のメンバーが触るまでにはなんらかの指針とかを決めないとなー、と思っています。
また、View間の相互作用とかを書くときに、ついViewを保有して〜とかやってしまいますが、これをちゃんとしたイベント駆動で書くクセを付けたいです。
こういうのが最近積み重なってきて、 Marionetteを利用しようと思ったのですが、jQueryのバージョン 1.8以上というのを見て涙を飲みました・・・。しばらくは頑張るしかなさそうです。
Backbone.jsを導入するときは
まずjQueryのバージョンを上げましょう。話はそれからだ。
それと、メンバーのJavaScript力を底上げする必要があると思いました。これはどんな現場でもそうだとは思いますが、どうしても全員が一定のレベルにはならないので、せめて平均点だけは上げておきたい、という願いです。
また、導入するときはMarionetteもまとめて導入したほうがよさそうです。Backbone.jsだけだと結構しんどい場面も少なくなかったので、私みたいな涙を飲む環境ではないのであれば、最初のコストを払ってでも導入しておくべきと思います。jQuery1.4.4は無いわー、と改めて思いました。
今のプロジェクトにはあと1年くらい突っ込まれそうな気はしていますが、進歩と変化を恐れず、より開発しやすい環境とライブラリを模索していきたいです。