レガシーな環境に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にしたのは、特に依存が無い、ということと安定していそうということで選択しました。

$.ajaxJSDeferredを利用した実装でラップして、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
  • jQueryjQuery 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年くらい突っ込まれそうな気はしていますが、進歩と変化を恐れず、より開発しやすい環境とライブラリを模索していきたいです。