読者です 読者をやめる 読者になる 読者になる

望月いちろうのREADME.md

書き溜めておいた技術記事や旅行記のバックアップです。

5分で理解するAngularJS | 初心者向け

JavaScript AngularJS

AngularJSとは?


  • Googleが開発した動的サイト(SPA)を作成するためのフレームワーク

  • JavaScriptで実装されている

  • 基本はMVCモデル

  • HTMLファイルに任意のコードを埋め込むことによって簡単にSPA化することができる。

SPA?

  • シングルページWebアプリケーションの訳

  • DOMを再構築することなくデータだけを差し替える

  • レンダリングの時間が削減されることによって大幅にユーザビリティの向上が期待できる。

実績

Googleの提供しているWebアプリケーションはほぼ全てAngularJSの上で構築されている

  • GoogleMaps
  • Gmail

など

初めてみる

1.HTMLファイルの中でAngularJSを利用することを宣言する。またアプリの名前を属性値として指定する。

命名規則としては慣例的にアッパーキャメルが使用されている。

<html ng-app="testApp">

2.AngularJSをCDNから読み込む

https://cdnjs.com/libraries/angular.js/

を参考に

<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.js"></script>

3.AngularJSのロジックを記述したJavaScriptファイルを作成する。

テスト段階では、scriptタグ内に直接書き込んでも構わない。

<script>
//testAppの宣言
var testApp = angular.module('testApp', []);
</script>

今回はapp.jsとして別ファイルとして管理することにする。

4.コントローラを宣言して、HTML内のDOM要素と関連づける

var testApp = angular.module('testApp', []);
testApp.controller('testAppController', function($scope) {
     //変数をセット
    
    $scope.title = "Hello World";
});

HTMLファイルに関連づけたいコントローラと同じ名前を指定する

<html ng-app="testApp">
<head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.js"></script>
     <script src="app.js"></script>
</head>
<body>
   <!-- この中でコントローラ内で指定した変数が利用できる -->
   <div ng-controller="testAppController"> 
      <h1>{{title}}</h1></div>
</body>
</html>

HTMLテンプレート内でコントローラで指定した変数を呼び出すには{{ }}で変数を囲う必要があります。

この例では、h1タグ内で指定されている{{title}}が該当します

5.ブラウザで表示することでAngularJSで作成したアプリが動作する

f:id:mochizuki_p:20170308184140p:plain


app.js内で定義したtitleが実際のWebページ内でも表示されていることがわかる。

AngularJSの面白い機能

スコープ内で使用できる関数

JavaScriptについての基礎的な知識を持って入ればJavaScriptでの関数は第1級であることをご存知だと思います。

つまり、AngularJSでも関数を変数としてscopeに格納してテンプレートの内部から呼び出すことが可能になります。

試しにh1タグ内のメッセージを消去する関数を定義してみます

var testApp = angular.module('testApp', []);
testApp.controller('testAppController', function($scope) {
     //変数をセット

     $scope.title = "Hello World";
    //関数を定義する
     $scope.deleteMessage = function() {

        $scope.title = "";

     }
})

特定のDOM要素がクリックされた際にこの関数が発火するように設定するにはng-clickで関数を指定します。

<html ng-app="testApp">
<head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.js"></script>
     <script src="app.js"></script>
</head>
<body>
   <div ng-controller="testAppController"> 
      <h1>{{title}}</h1>
      <button ng-click="deleteMessage()">消去</button></div>
</body>
</html>

inputの入力値とスコープ変数を関連づける

動的サイトで最も重要な機能の一つは入力値を使って、出力する値を切り替えることです。

そのためにはテンプレート内でng-modelを使用して、$scopeで定義した変数と関連づけます。

なお、初期値はng-initで、クエリ形式で与えます

<html ng-app="testApp">
<head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.js"></script>
     <script src="app.js"></script>
</head>
<body>
   <div ng-controller="testAppController"> 
      <h1>{{title}}</h1>
      <input ng-init="message={{title}}" type="text" ng-model="title"/></div>
</body>
</html>

このようにinputの入力値の変更に応じてtitleの値も変更されていることがわかると思います。

for文に相当するng-repeat

AngularJSのテンプレート内でfor文に相当する繰り返しを実行するにはng-repeatを利用します。

var testApp = angular.module('testApp', []);
testApp.controller('testAppController', function($scope) {
     //このオブジェクト内で、コントローラ内で使用する変数の管理を行う。
     $scope = {};
     //変数をセット
     $scope.languages = [
      {"name": "Python", "developer": "Guido van Rossum"},
      {"name": "Ruby", "developer": "Matsumoto Yukihiro"},
      {"name": "C++", "developer": "Bjarne Stroustrap"},
      {"name": "PHP", "developer" : "Rasmus Lerdorf"}
      ];
})
<html ng-app="testApp">
<head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.js"></script>
     <script src="app.js"></script>
</head>
<body>
   <div ng-controller="testAppController"> 
        <div ng-repeat="language in languages">
            <span> language: {{ language.name}}</span>
            <span> developer: {{language.developer}} </span>
        </div></div>
</body>
</html>

実際に出力してみると

f:id:mochizuki_p:20170308184148p:plain

JavaScriptでのオブジェクト指向プログラミング - 継承・オーバーライド

JavaScript

JavaScriptのオブジェクト志向プログラミングはプロトタイプチェーンと呼ばれる仕組みで設計されています。これはC++やJavaなどの標準的なオブジェクト指向プログラミング言語からすると分かりにくいです。

今回はJavaScriptでのプロトタイプチェーンを使ったプログラミングの手法を解説した後で、ES6から導入されたJava形式のオブジェクト指向記法を紹介します。

最初に

JavaScriptでのオブジェクト指向プログラミングは不完全なものです。

標準的なオブジェクト指向言語に備わっているprivateやpublicなどのアクセス権限のための属性を指定することはできません(少なくとも現時点では)

そのほかにも、様々な制約があります。あまりJavaScriptに多くのことを期待しないでください。

コンストラクタ

JavaScriptでオブジェクトを定義する時には、コンストラクタとなる関数を定義し、その名前をオブジェクトと結びつけます。

この例はRPGのモンスターに対応するオブジェクトを定義します。コンストラクタはヒットポイントと攻撃力、防御力を初期値として与えるものです。

var Monster = function (hitpoint, strength, defense) {this.hitpoint = hitpoint;
     this.strength = strength;
     this.defense = defense;

}

この時点でMonsterオブジェクトが定義できました。試しに適当な初期値を与えて、各属性値にアクセスをしてみます。

var monster = new Monster(100, 10, 5);
console.log(monster.hitpoint);
console.log(monster.strength);
console.log(monster.defense);

ブラウザやREPLなどで結果を試してみれば、それぞれ対応する値を取得できるはずです。

残念ながら、もし直接アクセッサを利用して値を改変してほしくない場合もJavaScriptではprivateなどの属性値を利用して制限をすることはできません。

クロージャやプレフィックスを利用したテクニックがあるそうですが、Mozillaの公式ドキュメントでは非推奨であるとされています。

将来的にはこの部分も改善されるということを期待して、あまりトリッキーなことはするなということです。

メソッド

コンストラクタの定義が済んだら次は個別のメソッドを定義します。各メソッドはコンストラクタの要素であるprototypeの子要素として定義します。

例えば、先ほどのMonsterのヒットポイントを取得したり、新しいヒットポイントを定義するメソッドはそれぞれ以下のようになります。

Monster.prototype.getHitpoint = function () {return this.hitpoint;

}

Monster.prototype.setHitpoint = function (hitpoint) {this.hitpoint = hitpoint;

}

Monster.prototype.attack = function () {return this.strength;

}  

実際にこのメソッドを使ってみましょう。

var monster = new Monster(100, 10, 5);

console.log(monster.getHitpoint()); // 100
console.log(monster.setHitpoint(90)); // ここでヒットポイントを90に変更
console.log(monster.getHitpoint());  // 90

継承

継承は通常、継承先のコンストラクタの中でcallを使って、継承元のコンストラクタを呼び出してから、継承先で新しく定義するプロパティを設定します。もちろんコンストラクタには継承元から引き継ぐ値と新しく定義するもの、両方を引数としてください。

今回はモンスター(Monster)を基底クラスとして、魔女(Witch)を定義することにします。

var Witch = function(hitpoint, strength, magicpoint) {
    Monster.call(this, hitpoint, strength);
    this.magicpoint = magicpoint;
}

次に各メソッドを継承するために継承先のprototypeに継承元のインスタンスを代入します。

Witch.prototype = new Monster();

これでMonsterで定義したメソッドが継承元のWitchでも利用できるようになりました。

継承先で新しくメソッドを定義する

あとは通常通り新しくメソッドを継承することができます。


Witch.prototype.healing = function () {this.magicpoint -= 2;
   this.hitpoint += 10;

}

オーバーライド

メソッドのオーバーライドは簡単で、継承先のprototypeに直接対応する新しいメソッドを書き込めば良いだけです。


Witch.prototype.attack = function () {
    return this.strength * 0.5;  
}

ES6でのオブジェクト指向プログラミング

従来のJavaScriptではプロトタイプチェーンを使ってメソッドの定義・継承を実行していました。しかしこの手法はJavaなどのオブジェクト指向言語に慣れていると分かりにくいと非常に評判が悪かったのも事実でした。

JavaScriptの新規格であるES6(ECMA Script 2015)ではJavaやC++などの一般的なオブジェクト指向言語に慣れたプログラマーにも分かりやすい記法を導入しています。今回はその定義・継承を中心に紹介してみようと思います。


基本的な記法はJava言語での記法に似たものになっています。

宣言

ES6ではclassに続いてオブジェクト名を明示することでオブジェクトを宣言します。 この例ではMonsterをクラス名としています。

class Monster {

}

コンストラクタ

ES6でプロパティの初期値を設定する場合はconstructor関数を利用します。constructor関数はインスタンスの確保時に実行され渡された引数をクラス内変数にセットします。

class Monster {
    constructor(hitpoint, strength) {
        this.hitpoint = hitpoint;
        this.strength = strength;
    }
}

コンストラクタには初期値を設定することも可能です。この場合引数が渡されなかった場合に、ageに20が代入されます。

class Monster {
    constructor(hitpoint = 100, strength = 20) {
        this.hitpoint = hitpoint;
        this.strength = strength;
    }
}

メソッド

メソッドは通常のJavaScriptの関数と異なる記法で宣言します。functionや=>は利用しないことに注意してください。基本的に関数名のみを指定してメソッドの定義を行います。 また、メソッド内でクラス内変数を呼び出す場合はthisの要素として呼び出してください。

メソッドを定義したスコープの後にコンマは置きません。

class Monster {
    constructor(hitpoint = 100, strength = 20) {
        this.hitpoint = hitpoint;
        this.strength = strength;
    }
    getDamage (damage) {this.hitpoint = this.hitpoint - damage;
        console.log("now your HP is " + this.hitpoint);
    
    }
    attack () {return this.strength;
    
    }
}

継承

あるクラスを継承して新しくクラスを宣言する場合はextendsで継承元のクラスを指定して元のクラスのメソッドを利用することができます。 


class Witch extends Monster{

}

また、継承元のコンストラクタを呼び出す場合は、継承先のコンストラクタ内で、super()を利用します。

class Witch extends Monster{
    constructor(hitpoint = 100, strength = 10, magicpoint = 20) {
        super(hitpoint, strength);
        this.magicpoint = magicpoint;
    }
}

オーバーライド

メソッドのオーバーライドに関しては明示的に宣言するプレフィックスが存在するわけではなく、単純に継承先のクラス内で再宣言を行えばよいだけです。

class Witch extends Monster{
    constructor(hitpoint = 100, strength = 10, magicpoint = 20) {
        super(hitpoint, strength);
        this.magicpoint = magicpoint;
    }
    // 元のattackをoverrideしている。
    attack () {return this.strength - 1;

    }
}

継承元のクラスのメソッドをオーバーライドしたメソッド内で利用することもできます。これを実行するにはsuperのメソッドとして呼び出すことで実行することができます。

class Witch extends Monster{
    constructor(hitpoint = 100, strength = 10, magicpoint = 20) {
        super(hitpoint, strength);
        this.magicpoint = magicpoint;
    }
    // 元のattackをoverrideしている。
    attack () {
        // 継承元のクラスのattackを呼び出している。
        super.attack()

        return this.strength - 1;

    }
}

また、単純にスーパークラスのメソッドをそのまま呼び出す場合は、継承先のクラス内で再定義などをする必要はありません。 


インスタンスの作成

インスタンスの作成は従来と同じでnewを使用して宣言を行います。

var monster = new Monster(50,10);
let e = new Witch();
e.getDamage(10); 

結果

now your HP is 90

糖衣構文

現時点でのclassを利用したオブジェクト指向プログラミングははプロトタイプチェーンの糖衣構文に過ぎないことに注意してください。つまり、内部では従来のプロトタイプチェーンと同じように扱われるということです。

こだわりのパンが食べられる京都の クロア に行ってきた

ご存知ですか?

京都市は1人あたりのパンの消費量が全国一なんです。和のイメージがあるのに意外ですね。

ところで、京都の北のはずれ、金閣寺よりもさらに北のほうに鷹峯と呼ばれる閑静なエリアがあります。

そこにあるパン屋さんにたまたま立ち寄ったら驚きの体験をしました。

散策をしていたらたまたま見つけた小さなパン屋さん

店名は「クロア(klore)」というそうです。

f:id:mochizuki_p:20170303194305j:plain

店内は南仏プロヴァンス風と言ったらいいのでしょうか?アイボリーホワイトを基調にしたムードになっています。

f:id:mochizuki_p:20170303194232j:plain

曜日は日曜、そして、もう午後の3時を過ぎていたのでほとんど商品は残っていませんでした。

こちらと

f:id:mochizuki_p:20170303194201j:plain

「トゥルヌ コンテチーズ+七味」

f:id:mochizuki_p:20170303194213j:plain

「クリームパン」に「クロワッサン」

f:id:mochizuki_p:20170303194222j:plain

とりあえずクロワッサン以外の3点を買ってみることにしました。

早速食べてみます

最初はクリームパン

ん〜f:id:mochizuki_p:20170303194817j:plain

このプリンの様な弾力がすごいカスタードクリームは、これだけでお菓子として通用しそうなおいしさ、バニラビーンズの香りが鼻に抜けていきます。

パンの生地はさっくりとした感じです。あくまで主役は中身のクリームなんですね〜

次は「トゥルヌ」

f:id:mochizuki_p:20170303194318j:plain

明太子というと、割と濃いめの味を想像してたのですが、結構あっさりとした感じです。

でもしっかりとしたうまみが後味として舌に残り、実際の分量以上に「食べた感」を感じさせるのですね。

何より素晴らしいのは皮の焼き具合の絶妙さ、食欲を刺激する香ばしさの引き出す最適解を導き出している感じですね。

噛むたびにチーズの香ばしい香りと風味が口の中に充満する感じです。

f:id:mochizuki_p:20170303194333j:plain

最後にこれも素晴らしいものでした。外はカリカリ、中はもっちりとしています。

素晴らしいのは食感で、食べていることをしっかりと感じさせながら、硬いとは決して思わせない。

そんな紙一重の絶妙のバランスなんですね。

f:id:mochizuki_p:20170303194339j:plain

う〜ん。これは今まで感じたことのない感覚だ・・

実は僕はあまりパンは好きではないのですが、今まで食べていたパンとは明らかに別物だと感じました。

これなら毎日食べても飽きないな〜と

何ていうか、安物のパンによく使われているショートニングやマーガリンがすごい苦手で、摂取すると気分が悪くなるんですよ。

f:id:mochizuki_p:20170303194327j:plain

でも、このお店のパンは多分バターしか使っていないんでしょうね。全く気分が悪くなることがならずに、すっとお腹に入る感じでした。

少しきつめの坂を登る必要はありますが、金閣寺観光など、近くに寄る機会があれば是非訪れるべきです。特にパン好きの方は必見です!

あと人気のお店なので、特に土休日は早めに訪問することをお勧めします!

クロア(klore)
住所 〒603-8445 京都市北区鷹峯藤林町 6 長八館1F
開店時間 朝9時から夕方6時まで
定休日 火・水曜日
アクセス 市バス6・北1系統 鷹峯上ノ町バス停よりすぐ

Mochaを使ってNode.jsのテストを自動化する

Node.js

前回はChaiを利用してNode.jsのTDD, BDDの導入法について紹介しました。

今回はMochaを利用して一連のテストを自動化する方法を紹介したいと思います。

Mochaの公式はこれです。

Mocha - the fun, simple, flexible JavaScript test framework

使い方

Mochaは通常グローバルにインストールします。

$ sudo npm install mocha -g

プロジェクトのホームディレクトリにtestフォルダを作成します。

この中にtest.jsを作成します。この中にテストのロジックを記述することになります。

package.jsonに追記

コマンド1つでmochaを使ったテストが実行可能になる様にpackage.jsonを編集します。 この中でmochaを開発時に限定して利用する様に設定を追加します。

また

$ npm test

でテストが実行できる様に設定を行います。 “scripts"に"test"を追記します。

"script":{
  ...
  "test":"mocha"
}
"devDependencies":{
  ...
  "chai": "*",
  "mocha": "*"
},

次はtest/test.jsの中身を編集します。

mochaで基本となるのはdescribe, itとその中のコールバック関数です。

describe('/*基本となるブロック*/', ()=> {
    it('/* 各テストの説明をここに書く */', (done)=>{
    /** 
    *  この中にchaiのテスト関数を記述する
    */
    });
});

実際には1つの大きなブロックとなるdescribe関数を用意した上で、その中に複数のdescribe関数を配置してテストをすることが多いようです。

describe('/*基本となるブロック*/', ()=> {

   describe('/*基本となるブロック*/', ()=> {
        it('/* 各テストの説明をここに書く */', (done)=>{
    /** 
    *  この中にchaiのテスト関数を記述する
    */
         });
    });

   describe('/*基本となるブロック*/', ()=> {
        it('/* 各テストの説明をここに書く */', (done)=>{
    /** 
    *  この中にchaiのテスト関数を記述する
    */
         });
    });

});

Expressでの利用例をここに示します。

Expressで画像を配信、投稿するAPIを整備したとします。この API に対するBDDを設定したいとします。

サーバーサイド(Express)はこのようになっています。

...

router.get('/:_id',(res,req,next)=>{
 
    Image.get(req.param.id,(err,image)=>{
        if(err) throws err;
        return res.send(image);
    });
});

router.post('/upload',(res,req,next)=>{
 
    Image.post(req.body.image, (err, result)=>{
        if(err) throws err;
        return res.send(true);
    });
});

このとき各ルーティングに期待する振る舞いを考えます。 つまり、

  • POST /upload - 画像を投稿する
  • GET /:id - IDに応じて画像を取得する

このときの各テストのロジックは以下のようになります。

  describe('#id()', function() {
    it('get without error', function(done) {
      chai.request('http://localhost:3000')
      .get('/schostakovich')
      .end((err, res)=>{ 
         expect(err).to.be.null;
         expect(res).to.have.status(200);
         done();
      });
    });
  });

  describe('#upload()', function() {
    it('save without error', function(done) {

        chai.request("http://localhost:3000")
        .post("/image")
.attach('image', fs.readFileSync('./test/image/schostakovich.jpg'), 'schostakovich.jpg')
        .end((err,res)=>{
            expect(err).to.be.null;
            expect(res).to.have.status(200);
            done();
        });
      
    });
  });


```

実際にテストを実行してみましょう

$ mocha

失敗した場合

  User
    #id()
      1) get without error
double callback!
    #upload()
      2) save without error
double callback!
  0 passing (53ms)
  2 failing

無事テストが通過したら以下のようになります。

$ mocha 
  User
    #id()
      ✓ get without error (79ms)
    #upload()
      ✓ save without error (783ms)


  2 passing (873ms)

いかがでしょうか?

このように複数のパスに対するテストを一括で実行可能なのがmochaの優れた特徴です。

スティーブ・ジョブズは悪の天才、騙されてはいけない

リチャード・ストールマン

スティーブ・ジョブズと言えば、天才的起業家の代名詞として多くの人の支持を集めています。

しかし、フリーソフトウェア運動の指導者であるリチャード・ストールマンはそうは思っていないようです。

それどころか彼は世界中の人々を騙した「悪の天才」であると断言しているのです。

f:id:mochizuki_p:20170222191501j:plain

ストールマンはスティーブ・ジョブズを名指しして、このようなコメントを残しています。

He is evil genius, He did harm to the world because he convinced people to rush stores saying “put the handcuffs on me please” and that is extremely harmful. that’s what we fight against.

奴は悪の天才だ。奴は世界にとって害をなす存在だった。なぜなら奴は人々をアップルストアに誘導して、進んで手錠を掛けさせるように仕向けたんだ。これは極めて有害なことで、僕が戦ってきたことなんだ。

これだけ言っても多くの人には何のことだか分からないと思います。

なぜストールマンはスティーブ・ジョブズに対して死人に鞭打つような形で、このような悪辣な言葉を投げかけるのでしょうか?

それはアップルコンピュータの発売する製品であるiPhoneやiPadがユーザーが使用できる機能に大きな制限を掛けていることがあります。

iPhoneを使用したことのある方ならお分かりと思いますが、iPhoneを始めとするアップルの製品の多くは、ユーザーが自由にソフトウェアをインストールすることができないという特徴があります。ユーザーはアップルの管理するApple Storeを通じてのみ、アップルが許可したアプリをインストールすることを許されます。

しかし、このことはフリーソフトウェア運動の信奉者からしたら耐えられないことです。彼らは自分の好きなソフトウェアを、自分のコンピュータに自由にインストールすることが、基本的人権の一つだと信じています。

実際に彼らは自分自身のコミュニティ内でフリーソフトを数多く作成し、人々にそれを使ってもらうように日々努力しているのです。

Steve Jobs figured out how to build computers that were prisons and jails for the user and how to make them stylish and chic.

スティーブ・ジョブズはおしゃれでシックに見える一方で、実際には監獄のようなコンピュータを作り、人々が進んでそれを使うように仕向ける方法を考案したんだ。

実際にアップルの数々の経営戦略は彼らの価値観と真正面に対立するものばかりです。リチャード・ストールマンは「Appleを使ってはいけない理由」として複数の事実を挙げています。

Reasons not to use Apple

特に物議を醸したのはスティーブ・ジョブズが2011年10月5日、膵臓癌で亡くなった時に残したコメントです。

Steve Jobs, the pioneer of the computer as a jail made cool, designed to sever fools from their freedom, has died. As Chicago Mayor Harold Washington said of the corrupt former Mayor Daley, “I’m not glad he’s dead, but I’m glad he’s gone.” Nobody deserves to have to die - not Jobs, not Mr. Bill, not even people guilty of bigger evils than theirs. But we all deserve the end of Jobs' malign influence on people’s computing. Unfortunately, that influence continues despite his absence. We can only hope his successors, as they attempt to carry on his legacy, will be less effective.

スティーブ・ジョブズ、馬鹿どもが自ら進んで自由を放棄する監獄のようなコンピューターの先駆者が、死んだ。

かつてのシカゴ市の市長の ハロルド・ワシントン が腐敗した前市長 ダレイ を指して言った言葉に"私は彼が死んで嬉しいわけではないが、彼がいなくなって嬉しい" がある。

誰も死ななければならないということはない。ジョブズやビル・ゲイツ、彼ら以上の悪事をなした人々もそうだ。 しかし、私たちは、ジョブズが残した人々のコンピュータの利用についての悪影響を終わらせる責任があるだろう。 不幸なことに、彼が死んでも影響は世の中に残り続けるだろう。私たちが望むのは、彼の遺産を継ぐ後継者がそれほど有能でないことだ。

・・・

僕自身はスティーブ・ジョブズは偉人であると思っていますし、アップルの製品が大好きです。また、Linuxを始めとするフリーソフトも大好きなので、複雑な心境です・・

Chai と Mocha でNode.jsのテスト自動化をやってみる | Node.js

Node.js

テスト駆動開発(TDD)とその派生の振る舞い駆動開発(BDD)は最近では一般化しているように思えます。

今回はNode.jsでTDDとBDDを行うためにライブラリであるChaiを紹介したいと思います。

Chai

chaijs.com

チャイと呼びます。あのスパイシーなインドの甘いミルクティーが語源でしょう

導入するには

sudo npm install chai  

devDependenciesに追記します。

つまりは開発ステージで限定して利用するという意味です。

"devDependencies": {
  "chai": "*"
}

BDD

Chaiを利用したBDDの基本になるのは次の2つの要素です

  • expect
  • should

expectでは特定の型の値、あるいはある範囲の値を返して欲しいと言ったように、特定の変数に対する期待を指定します。 もし指定した条件に一致しなければテストは失敗になるわけです。

expectを読み込む

'use strict';

const chai = require('chai')
const expect = chai.expect;

例を挙げます。RESTful APIでJSON形式のレスポンスを返す特定のルーティングの対してのテストを実行したいとします。 例えば、GET /user は以下の条件を満たさないといけないとします。

  1. ユーザーのIDを入力する
  2. リクエストが成功する
  3. IDに対応するユーザー情報がレスポンスとして帰ってくる

それに加えて

  • 実際にjson形式でレスポンスが返ってくる
  • ユーザー名"name",メールアドレスがレスポンスの値に入っている必要がある

この条件を満たす様なテストを設定するにはHTTPリクエストを行わせる必要があります。 そのためにはchai-httpを導入する必要があります。

sudo npm install chai-http

chai-httpを実際に使用するにはchaiから読み込ませる必要があります。

chai.use(chaiHttp);

これでchaiからhttpリクエストが行える様になりました。

次に実際のテストの中身を記述します。

chaiの記述はパイプになっています。左側に処理した値が右側に渡される仕組みです。

今回実行するテストの順番をもう一度確認して見ましょう

  1. ローカルホストの3000にリクエスト(Expressアプリケーションが起動している)
  2. /userにリクエスト
  3. 返り値をexpectでテストする

テストコードを全てまとめると・・

'use strict';

const chai = require('chai')
const expect = chai.expect();
const chaiHttp = require('chai-http');

chai.use(chaiHttp);

chai.request('http://localhost:3000')
.get('/users?id=3a828a3b258')
.end((err, res)=>{ 
   expect(err).to.be.null;
   expect(res).to.have.status(200);
   expect(res).to.be.json;
   expect(res.body).to.have.property('name');
   expect(res.body).to.have.property('email');
});

これをtestディレクトリに配置します。

localhost:3000でREST APIを起動している状態でこれを起動します。

node test/test.js

もし何のエラーも発生しなければOKです。

もしテストが失敗すればAssertionErrorが発生します。

AssertionError: expected { Object (domain, _events, ...) } to have a property 'name'
...

mochaを使う

mochaを利用することで複数のテストを一括で処理することが簡単になります。

これは次回に紹介します。

Go言語の静的サイトジェネレータHugoを使ってサイトを作成する

Go言語 Hugo

前回ではHugoでテーマを導入してサイトのトップ画面を作成するところまで進めました。

今回は公開できるレベルまでサイトを作り込んでいこうと思います。

とりあえず記事を投稿してみましたがサムネイルがなく殺風景です。記事に対応する画像を貼る様にします。

画像などの静的ファイルを配置する

Hugoでは静的ファイルはホームディレクトリ以下のstatic内に配置する必要があります。

ここに画像ファイルを格納するためのimgディレクトリを配置してみましょう。

特に理由はありませんがRMSの画像を利用することにします。

f:id:mochizuki_p:20170227223856p:plain

次に記事に移動します。

テーマにもよりますが記事のサムネイルを指定するにはimageにstaticフォルダからの相対位置で画像ファイルを指定します。

+++
image = "/img/hello_world.jpg"
date = "2017-02-26T17:39:47+09:00"
title = "hello world"

+++

# Hello World

Hello World

これで記事に画像が関連付けられたはずです。

試しに確認してみましょう。

f:id:mochizuki_p:20170227223748p:plain

固定ページを作成する

サイトの概要や著作権表記など、固定ページを作成することも可能です。そのためには

  1. content以下に固定ページ用のディレクトリを作成する
  2. 1で作成したディレクトリ内にindex.mdを作成して内容を編集する。
  3. config.tomlで作成したディレクトリを登録する。

試しにサイトの概要を説明する固定ページとしてaboutを設置してみようと思います。 


mkdir about
touch index.md

index.mdの内容は

++++

title = "About us"
date = "2017-02-27T12:04:48.782Z"

+++

About us



config.tomlを編集

config.tomlにこの固定ページを登録します。

テーマごとに指定された値を登録するために [param]というブロックを配置します。

この中にインデントを下げて params.navlinksを作成します。 ここにname=“About"でナビゲーションを作成してcontent内のディレクトリを指定します。

ついでにSNSのアカウントも表示することにしましょう。 あなたのSNSのアカウントをここに指定しておくとサイトの下部にリンクが表示されます

[param]

  [[params.navlinks]]
  name = "About"
  url = "about/"

  [params.social]

  facebook      = "https://www.facebook.com/example"
  twitter       = "https://www.twitter.com/example"

これで再びサイトを生成

見てみると

f:id:mochizuki_p:20170227223811p:plain

この様に各固定ぺージへのリンクが入ったナビゲーションが作成されました。

そして各ページの下部にはSNSへのリンクが表示されています。

静的サイトはどこに配置されているのか?

Hugoは静的サイトジェネレータです、各ページごとにHTMLファイルが作成され、それに付随した画像などのメディアファイル、CSSやJSがひとまとめになったディレクトリが生成されます。これをApacheなどのサーバーで配信する様にすればWebサイトの出来上がりです。

静的サイトを生成するには

hugo

生成されたWebサイトのデータはpublicディレクトリ内に配置されます。このディレクトリの中身を丸ごとWebサーバーにアップすれば完了です。

生成されたWebサイト

public
├── about
│   ├── index.html
│   └── index.xml
├── categories
│   └── photography
│       ├── index.html
│       └── index.xml
├── contact
│   ├── contact
│   │   └── index.html
│   └── index.xml
├── css
│   ├── bootstrap.min.css
│   ├── bootstrap.min.css.map
│   ├── custom.css
│   ├── font-awesome.min.css
│   ├── fonts
│   │   ├── FontAwesome.otf
│   │   ├── fontawesome-webfont.eot
│   │   ├── fontawesome-webfont.svg
│   │   ├── fontawesome-webfont.ttf
│   │   ├── fontawesome-webfont.woff
│   │   └── fontawesome-webfont.woff2
│   ├── helper.css
│   ├── owl.carousel.css
│   ├── owl.theme.css
│   ├── owl.transitions.css
│   ├── style.blue.css
│   ├── style.default.css
│   ├── style.green.css
│   ├── style.pink.css
│   ├── style.red.css
│   ├── style.sea.css
│   └── style.violet.css
├── img
│   ├── hello_world.jpg
│   └── rms.png
├── index.html
├── index.xml
├── js
│   ├── bootstrap.min.js
│   ├── ekko-lightbox.js
│   ├── front.js
│   ├── imagesloaded.pkgd.min.js
│   ├── jquery.cookie.js
│   ├── jquery.min.js
│   ├── jquery.scrollTo.min.js
│   ├── main.js
│   ├── masonry.pkgd.min.js
│   └── owl.carousel.min.js
├── post
│   ├── hello-world
│   │   └── index.html
│   ├── index.xml
│   └── rms
│       └── index.html
├── scss
│   └── main.scss
└── sitemap.xml

続く

Go言語の静的サイトジェネレーター Hugo を使ってみる

f:id:mochizuki_p:20170213214140p:plain

WordPressのようなCMSは便利な様で便利でない・・

MySQLを始めとするデータベースの設定は面倒ですし

だからと言って、HTML手打ちに戻るなんて論外です。

しかし、静的サイトジェネレーターを使えば、CMSの感覚で簡単に静的サイトをデプロイすることができるよ。というのが今回の記事の伝えたいところです。

Go言語で構築されたHugoは非常に優れた特徴を持った静的サイトジェネレータです。

  • 豊富なテンプレート
  • 生成速度の速さ
  • CMS並みの豊富な機能・拡張性

インストール

MaxOS(OS X)

もしGo言語が入っていない場合は

brew install go 

Hugoをインストール

brew install hugo

インストールを確認

$ hugo version
> Hugo Static Site Generator v0.18.1 BuildDate: 2016-12-30T02:12:41+09:00

サイトを作成

最初にサイトの名前を決めてhugo new siteで生成します。 ここでは例としてMyHomepageにしてみましょう。

hugo new site MyHomepage

成功するとカレントディレクトリにMyHomepageが生成されます。 中に入って続きの作業を行います。

テーマを導入

サイトを生成する前に、テーマを選ぶ必要があります。

ご覧の通り/themesにはまだ何のテーマもインストールされていません。

$ tree -a

├── archetypes
├── config.toml
├── content
├── data
├── layouts
├── static
└── themes

公式からテーマを選びましょう。確認できる限り全て無料でした。

Hugo Themes Site

f:id:mochizuki_p:20170226180223p:plain

今回はこの"TRACKS"を利用してみることにしましょう。

/themesに入ってGitで取得します。

$ cd themes
$ git clone https://github.com/ageekymonk/hugo-tracks-theme.git

設定ファイル(config.toml)

$ cd ..
$ vi config.toml

デフォルトではこの様な内容になっているはずです。

languageCode = "en-us"
title = "My New Hugo Site"
baseurl = "http://example.org/"

ここにテーマを指定するために以下の内容を追記します。 そして上記の値も適切に書き換えます。

languageCode = "ja-ja" # 言語のコード
title = "MyHomepage" # サイトのタイトル
theme = "hugo-bootstrap-premium " # 使用したいテーマ、後で変更することも可能

これでとりあえず起動することが可能

hugo server 

ブラウザでlocalhost:1313にアクセスしてみよう

f:id:mochizuki_p:20170226180240p:plain

この様にトップページが表示された。

f:id:mochizuki_p:20170226180232p:plain

しかし、これではあまりに殺風景だ。記事を投稿する。

hugoでは記事はマークダウン形式で、content/post以下に作成する

以下のコマンドを打つとcontent以下に新しい記事のひな形が作成される

hugo new post/hello-world.md
```
tree -a


├── archetypes
├── config.toml
├── content
│   └── post
│       └── hello-world.md
├── data
├── layouts
├── static
└── themes

hello-world.mdの中を編集しよう

+++
date = "2017-02-26T17:39:47+09:00"
title = "hello world"

+++

+++で囲まれたtoml形式の記述でタイトルなどのメタデータを決定する。

その下にマークダウン形式で記事を書くことができる。

試しに以下の内容で書いてみる

+++
date = "2017-02-26T17:39:47+09:00"
title = "hello world"
# もし下書きとして公開したくない場合は以下をコメントアウト
# draft = true
+++

# Hello World

Hello World

保存したらさっきと同じ様にしてデプロイ

hugo server

f:id:mochizuki_p:20170226180303p:plain

/hello-worldにアクセスすると

f:id:mochizuki_p:20170226180252p:plain

もしなんとなく導入したテーマが気に食わなければ簡単に交換することができる。themesに任意のテーマを導入して、オプションで指定するだけで変更できる

hugo server --theme=hugo-bootstrap-premium

f:id:mochizuki_p:20170226180318p:plain

次回の記事では実際に作成したサイトをデプロイするところまでやってみたいと思います

なぜハンドメイドの品がこんなにも売れるのか?京都・知恩寺 手づくり市 に見る小商いの将来性

f:id:mochizuki_p:20170225163836j:plain

京都市左京区の百万遍、京都大学の真向かいにある知恩寺で毎月15日に開催されるイベントがある。 百万遍さんの手づくり市の名で知られるフリーマーケットである。

なにもフリーマーケットだけならばありふれたものであるが、この手づくり市の個性的なポイントは、ハンドメイド品だけが出品できることだ。仕入れたものは原則出品することができない。

何より驚くのはその動員力である。開催日には最寄りの駅から長い人の波が途切れることがなく、かつ会場は熱気にあふれ、各店舗には行列が絶えることがない。

出品される商品のラインナップは非常に多い。自家製のパンやジャム、漬け物、自家採取のはちみつといった食品はもちろん、和紙製の帽子やレザークラフト、楽器、手づくり石鹸などは見ているだけでも楽しいものだ。

f:id:mochizuki_p:20170225164044j:plain

正直にいって価格は市販品に比べてかなり割高だ。

パンなどは少し大きめであるが平気で400円、500円といった値段をつけている。

f:id:mochizuki_p:20170225163922j:plain

似たようなものをスーパーなどで買えば半額ほどで済むだろう。それでも次から次へと人がやってきて、商品は飛ぶように売れていく。

f:id:mochizuki_p:20170225164059j:plain

人々はこれらのハンドメイド品にどのような価値を見出し、高い値段を払っているのであろうか?

一つは作り手の顔を直接見ながら商品を選ぶことができるところである。

f:id:mochizuki_p:20170225164123j:plain

現代の複雑化した生産流通体制の中で、消費者が作り手の姿や想いを知ることは難しい、コンビニで売っているおにぎりを例に挙げればいいだろう。

実際に、誰がどんな思いを込めてこのおにぎりを作ったのか?

どんな材料や使って、どんな風に運ばれたのか?

消費者は店頭でなにも情報を得ることができないのである。

しかしこの手づくり市では実際に商品を作った人と直接顔を合わせて商品を購入することができる。

店頭に立っている人と会話をすることで、その人柄や、商品に込められた想いを伺うことも可能である。

f:id:mochizuki_p:20170225164137j:plain

この作り手が使う人と直接取引きするということはかなりポジティブなフィードバックを与えているだろう。

実際に使用する人の顔を見て、直接コミュニケーションをとることで、作り手は自分の仕事に対する明確なやりがいを感じることができ、それが製品に対するさらなる改良のモチベーションにつながるからである。

2つ目は、消費者が工場で大量生産された安い品に飽きていることがあるだろう。

f:id:mochizuki_p:20170225164159j:plain

市場には海外の工場で安い人件費で大量生産された製品があふれている。

そのような製品の品質は非常に安定しているし、何よりとても安く手にいれることができる。

しかし、それは裏を返せば没個性な、面白みのない品であり、作り手の想いやこだわりのこもっていない。

言わば単なる無機質な物質に過ぎないという側面がある。

しかし多くのハンドメイド品には工場で量産された安物との明確な違いがある。

それは作り手が自分が欲しいもの、作りたいもの、最高だと思うものを形にしていることである。

f:id:mochizuki_p:20170225164228j:plain

海外の工場で量産された安物にはそれを感じることが困難だろう。

工場で実際にモノを作るのは、安い時給で働く労働者である。

労働者が考えているのは最低限のノルマをこなし、要領よく時給をもらうことである。

そこには製品に対する愛情や思い入れというものは皆無に等しいだろう。

f:id:mochizuki_p:20170225164250j:plain

そして何よりも筆者がこの手づくり市に強く関心をもつのは、このようなハンドメイド品をつくる自営業者(多くは個人事業主)が、強大な資金力をもった大企業の製品に対して、ある意味で明確な優位性を発揮して、正面から対抗することができるということにある。

これらのハンドメイド品は、相対的に高価であるけれども、その個性と、何よりも作り手の思い入れを感じることができるという点で、大きな競争優位性をもっているのである。

アクセス

京都・知恩寺の手づくり市
開催 毎月15日
アクセス 京阪電車・出町柳駅から徒歩15分 京都市バス・百万遍バス停からすぐ

TwitterはScalaを捨ててNode.jsに移ったそうです。

Node.js Scala

f:id:mochizuki_p:20161005031521j:plain

世界で最も大きなトラフィックを捌いているサービスの1つであるTwitterはそのバックエンドをScalaで独自開発したフレームワーク(Finagle)を採用していましたが、ここ数ヶ月の間にこれをNode.js(Express)に置き換えたそうです。

以下はTwitterのエンジニアであるNicolas Gallagherさんのツィートより

github.com

本日をもってTwitterのモバイルWeb版のトラフィック(たくさん)を僕たちの新しいWebスタックに移行した。つまり、Node.js、ExpressそしてReact Progressive Web Appだ。

このJavaScriptのスタックは今から9ヶ月前から実運用に入っていた。ログイン済みのモバイルWebユーザー向けにね。

2年の間、ログインしていないユーザーのトラフィックはScalaとGoogleのClosureテンプレートを中心に捌いていた。

数ヶ月間にCharlie Croomがログインしていないユーザーのトラフィックの一部をJavaScriptのスタックに置き換える実験を始めた。

今週にはJames Bellenger(僕たちのチームのNode.jsの帝王)が残りのログインしていないユーザーのトラフィックをScalaからJavaScriptに移行した。

個人的な意見ですが、Scalaは美しい仕様を持つ素晴らしい言語ですが、関数型+オブジェクト指向という特徴から、学習コストが高すぎると感じました。そして実運用をするには、それに加えてJavaのライブラリの知識やJVMのパフォーマンスに気を配る必要があります。つまり、面倒すぎる言語なのでしょう。

一方でNode.jsはチープなマシンでも高いパフォーマンスが出せるような設計になっており、何よりJavaScriptであることからフロントエンドと使用する言語を共通化できるという利点があります。

これについてはTwitterのエンジニアでもある James Bellengerさんも

Node.jsは今まで致命的な問題が発見されたことはなく、そしてサーバーと同じコードで動作させることができるという利点はとても大きい。

これには、Twitterの特殊事情がありそうで、REST APIがjson形式でデータをやり取りしていることから、そのパースにかかる計算コストが大幅に削減されたことがありそうです。JSONはJavaScriptのデータ型そのものですからね。

Node.jsの導入による最高の収穫はTwitterのRest APIの性能の改善だ。それに加えてたくさんの収穫がある。

総合すれば、JSONのパースにかかる時間の削減がとても効果的だった。graphQLの導入も視野に入れているよ

とにかく秒間10万アクセスにも及ぶ大量のトラフィックを捌いているTwitterがNode.jsを採用したことで、またNode.jsの優位性を証明する結果になりました。