【技術的詳細】車のローン/燃料費シミュレータについて

車のローン/燃料費シミュレータの裏側処理の詳細です。

 

ライブラリ群

Knockout.js

メインで使っているのはKnockout.jsです。MS社員が開発したとても素敵なライブラリです。学習コストが少なく、各コードの量は大幅に削減されます。

キーとなる思想はバインディングです。シンプルなJavascriptオブジェクトの値を画面上の要素と結びつけて動的に更新します。基本的にはSPA(Single page web application)などの構築で用い、Ajaxで取得したデータでゴリゴリと画面を更新していくような用途で使われることを想定していますが、今回のように各コントロール間に関連があり、それをもとに動的に値を更新する、なんて用途にも使うことができます。

jQueryUI

説明不要のライブラリ。スライダーコントロールを簡単に実現させるためにはこいつが便利です。

jQuery UI Touch Punch

jQuery UIのスライダーをスマホに対応させるためのライブラリです。jQuery UIの次にincludeしてあげるだけで良く、コードは何も変更しなくとも動作しました。中身を見ていないのですが、jQuery UIのオブジェクトを書き換えているのでしょう。動的言語はこういうことが容易にできるので便利ですね。

Knockout-jQueryUI

Knockoutにバインドできるのはhtml要素の各属性です。jQuery UIのスライダー値などに対応させるためには自分でイベントを拾って手書きしなければなりません。これではKnockoutの良さも半減、いや、1/3くらいになってしまいます。

これを使えばjQuery UIの各コントロールに対して値を直接バインドできます。

コード

以下が車を表現するオブジェクトです。

var car = function () {
    this.efficiency = ko.observable(37.0);
    this.weight = ko.observable(1070);
    this.price = ko.observable(1370000);
    this.interest = ko.observable(0.04);
    this.isDiesel = ko.observable(false);

    var _this = this;

    this.costOfMonth = function (gas, oillight, distance) {
        if(_this.isDiesel())
            return distance / 12 * oillight / _this.efficiency();
        else
            return distance / 12 * gas / _this.efficiency();
    };
};

特に複雑なところはなく、直観的に理解できると思います。単純な値はko.observable()を使って関数を入れ込みます。こいつはfunctionを返すので、値を入れるときはcar.weight(1400);などとし、取得するときはvar w = car.weight();とします。getter/setterのような感じですね。

var fuel = function () {
    this.distance = ko.observable(8000);
    this.costOfGassoline = ko.observable(160.0);
    this.costOfOillight = ko.observable(135.0);
    this.initialPay = ko.observable(500000);
    this.loanYears = ko.observable(6);
    
    this.car1 = new car();
    this.car2 = new car();
    // ...以下略
};

var vm = new fuel();
$(function () { ko.applyBindings(vm); });

上のコードがViewModelになります。こいつをapplyBindingsに与えてあげればバインドが開始されます。この操作は一度だけで良いです。更新通知するたびに呼ぶなどの操作は不要です。

あなたの年間走行距離:<span data-bind="text: distance"></span>km
<div class="distanceBar slider" data-bind="slider: {value: distance, realtime: true }"> </div>

 html側は上記のような感じになります。バインド先の変数名を呼んでいるだけです。Knockoutが偉いのはここでバインドさせるだけでなく、コードを書けちゃう事です。たとえば、上記のバインド先であるdistanceをdistance + 10と書けば10加算された値が表示されますし、Math.round(distance)と書けば丸められた値が表示されます。

 

所感

 

Knockoutは本当に良いフレームワークだと思います。決まりきったコードをだらだらと書く必要も無く、値の変更通知をイベントを取って値を設定して~という面倒な処理をぐだぐだ書かなくてもよく、ひたすら「どういうデータを持つか」「どうやって計算するか」「どうやって表示するか」 だけにフォーカスできます。

私はC#+WPF+Entity Frameworkという組み合わせが大好きですが、それらで得られる恩恵とKnockoutが提供する快適さというのはかなり似ています。シンプルな分、Knockoutのほうがむしろ便利という気さえしています。バインドするときにコードを書けるのが良いですね。動的言語である利点がフルに生かされていると思います。

ただそれでも開発していてちょっと嫌だったのは、observableな値を取得するときに本来vm.distance()と書くべきところをvm.distanceと書いてしまうなどのケアレスミスが多々あり、これが簡単に気付けないことです。静的型付け言語であればコンパイル時というかIDEでコードを書いた瞬間に気付くことですが、Javascriptだとデバッガを当ててみて初めて気づく場合が多いです。ここらへんはTypeScriptも併用すればいいのかもしれません。後で書き直してみるつもりです。

ちなみに、Visual Studioを使うと、HTML側でバインドさせるときに補完が利くのでさらに楽です。もちろん無償のExpressでも可能です。