うごく生ゴミプログラマの備忘録

うごく生ゴミ 〜再臨〜

React + gulp サンプル

Material Design Lite

www.getmdl.io

React

facebook.github.io

React使いつつ、マテリアルデザインも使いたいなーと思って、Material Design Lite を組み合わせてみた時のメモ。

ビルドツールには gulp を使用したので、まず gulpfile.js から。

var gulp = require('gulp');
var uglify = require('gulp-uglify');
var plumber = require('gulp-plumber');
var browserify = require('browserify');
var source = require("vinyl-source-stream");
var reactify = require('reactify');
var buffer = require('vinyl-buffer');


gulp.task('dist', function(){
  var bundler = browserify('./script/src/main.jsx', { debug: true });
  return bundler
        .transform(reactify)
        .bundle()
        .pipe(plumber())
        .pipe(source('build.js'))
        .pipe(buffer())
        .pipe(uglify())
        .pipe(gulp.dest('./script/dist/'));
});


gulp.task('watch', function() {
    gulp.watch('./script/src/*.js', ['dist']);
    gulp.watch('./script/src/*.jsx', ['dist']);
    gulp.watch('./script/src/**/*.js', ['dist']);
    gulp.watch('./script/src/**/*.jsx', ['dist']);
});


gulp.task('default', ['dist', 'watch']);

次に HTMLファイル。 body要素の最後で、ビルド後のjsファイルを読み込むようにする。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title>test</title>
    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
    <link href="./style/material.min.css" rel="stylesheet">
    <link href="./style/style.css" rel="stylesheet">
  </head>
  <body>
    <noscript>JavaScriptを有効にして下さい。</noscript>
    <div id="appView"></div>
    <script src="./script/dist/build.js"></script>
  </body>
</html>

エントリーポイントとなる main.jsx 3行目で、Material Design LiteのJavaScriptを読み込んでいる。 6行目で読み込んでいる AppView.jsx がルートコンポーネント

(function () {
    'use strict';
    var mdl = require('material-design-lite');
    var React = require('react');
    var ReactDOM = require('react-dom');
    var AppView = require('./component/AppView.jsx');

    // アプリケーション全体のコンポーネントを表示
    ReactDOM.render(
        <AppView />,
        document.getElementById('appView')
    );

}());

Go言語インストールからHelloWorld、あと特徴とか忘れないうちにメモっとく

インストール手順

MacにHomebrewを使ってインストールした。Homebrewはインストール済の前提。

$ brew install go

バージョンを確認

$ go version

Hello World!

package main

import (
  "fmt"
)

func main() {
  fmt.Println("Hello World!")
}

Hello World 実行手順

自分は以下のような sh ファイルを作った。

今回はとりあえず test.sh という名前で保存した。

export GOPATH=任意のパス
export PATH=$PATH:$GOPATH/bin
cd ${GOPATH}
go install ./src/github.com/jsuzuki20120311/go_test

Hello Worldのソースが書けたら、

$ ./test.sh

その後、別窓でターミナルを開いて

$ ./go_test
Hello World!

Hello World! が出力されればめでたしめでたし。

その他、Hello Worldやる過程で調べてわかったこととかメモ

クラスなんてものは無い 代わりに 構造体 なるものがある

実際に書いてみた。

    type box struct {
        width int
    }
     
    func (b *box) get_width() int {
        return b.width
    }
     
    func main() {
        b := box{width: 10}
        fmt.Println(b.get_width())
    }

他、継承なんてない。コンポジッション関係を使え。あとインタフェースはある。 このあたりを箇条書きにすると

  • is - a 関係 : × 代わりに has - a 使え
  • has - a 関係 : ○
  • can do 関係 : ○

また別の日にもう少し詳しく整理して書こうと思う。

自前でクライアントサイドMVCのModelとView用ライブラリ作った

自前でクライアントサイドMVCのModelとView用ライブラリ作った。

github.com

コンセプトは、以下のような見慣れたクラス定義の書き方を崩さずかけるようにすること。

/**
 * サンプルクラス
 */
var SampleClass = function () {
    // 何か処理
};


/**
 * サンプルメソッド
 */
SampleClass.prototype.sampleMethod = function () {
    console.log('sampleMethod');
};

今回作ったBellTreeMVを使用する場合、例えばModelを定義する場合以下のように書く。

/**
 * サンプルModel
 */
var SampleModel = function () {
    BellTreeMV.Model.call(this);
};

BellTreeMV.inheritPrototype(SampleModel.prototype, BellTreeMV.Model.prototype);

SampleModel.prototype.sampleMethod = function () {
    console.log('sampleMethod');
};

必須なのは

    BellTreeMV.Model.call(this);

BellTreeMV.inheritPrototype(SampleModel.prototype, BellTreeMV.Model.prototype);

の行のみ。 あとは昔からある見慣れたコンストラクタ関数の定義と、prototypeにメソッドを定義しているだけ。

まだまだライブラリと呼ぶにはあまりに拙く機能もすくないけど、わりと自己満足はできてるし、オブザーバパターンの良い勉強になった。

React + browserify 用 gulpfile メモ

React で browserify を使用する場合用のgulpfileを作ったのでメモ。 99%自分のメモ用。

uglify がファイルを縮小させるやつ。 plumber がビルドで失敗しても、ファイル変更の監視をやめないようにするやつ。 reactify がJSXをJavaScriptに変換するやつ。

var gulp = require('gulp');
var uglify = require('gulp-uglify');
var plumber = require('gulp-plumber');
var browserify = require('browserify');
var source = require("vinyl-source-stream");
var reactify = require('reactify');
var buffer = require('vinyl-buffer');


gulp.task('dist', function(){
  var bundler = browserify('./script/src/main.jsx', { debug: true });
  return bundler
        .transform(reactify)
        .bundle()
        .pipe(plumber())
        .pipe(source('build.js'))
        .pipe(buffer())
        .pipe(uglify())
        .pipe(gulp.dest('./script/dist/'));
});


gulp.task('watch', function() {
    gulp.watch('./script/src/*.js', ['dist']);
    gulp.watch('./script/src/*.jsx', ['dist']);
    gulp.watch('./script/src/**/*.js', ['dist']);
    gulp.watch('./script/src/**/*.jsx', ['dist']);
});


gulp.task('default', ['dist', 'watch']);

Effective Java の BuilderパターンをJavaScriptで書いてみた

Javaの参考書のなかでよくおすすめと言われている Effective Java で紹介されている Builder パターンを、JavaScript で書いてみた。

Effective Java ってなんやそれ、っていう方はこちら。

Amazon.co.jp: EFFECTIVE JAVA 第2版 (The Java Series): Joshua Bloch, 柴田 芳樹: 本

普通に Java で書かれたコードについてはこちら。Effective Java で紹介されているBuilderパターン意外も紹介されています。とてもわかりやすかったです。

Javaで書くBuilderパターンのパターン - Qiita

Builder パターンを使用しない場合

ここでは、以下のユーザ情報を登録できるシステムを想定して、ユーザ情報を保持するオブジェクトの生成を例にみていく。 * 名前(必須項目) * 年齢 * 郵便番号 * 住所 * 血液型 * 星座 * 好きな食べ物

以下 Builder パターンを使用しない場合のコード。 引数ですべての属性を指定している。

/**
 * ユーザクラス
 * @param {String} name          
 * @param {Number} age           
 * @param {String} postalCode    
 * @param {String} address       
 * @param {String} phoneNumber   
 * @param {String} boodType      
 * @param {String} constellation 
 * @param {String} favoriteDish  
 */
var User = function (name, age, postalCode, address, phoneNumber, boodType, constellation, favoriteDish) {
    'use strict';

    if (!name) {

        throw new Error('必須項目[名前]が未設定です。');
    }

    this.name = name;
    this.age = age;
    this.postalCode = postalCode
    this.address = address;
    this.phoneNumber = phoneNumber;
    this.bloodType = boodType;
    this.constellation = constellation;
    this.favoriteDish = favoriteDish;
};

User.prototype.toString = function () {
    'use strict';
    var string = (' 名前: ' + this.name 
        + ' 年齢: ' + this.age 
        + ' 郵便番号: ' + this.postalCode
        + ' 住所: ' + this.address
        + ' 電話番号: ' + this.phoneNumber 
        + ' 血液型: ' + this.bloodType
        + ' 星座: ' + this.constellation
        + ' 好きな食べ物: ' + this.favoriteDish)
        ;
    return string;
};

// 新規のユーザを作成
var user = new User('数多の世界を救済した勇者 ああああ', 60, 'XXX-XXXXX', '勇者の城(旧魔王の城)', 'XXX-XXXX-XXXXX', 'AB', '乙女座', '牛ヒレ肉とフォアグラのロッシーニ');

このコードの悪いところ (1つめ)

オブジェクトを生成するタイミングで、引数の順番を間違いやすい。 第二引数くらいまでは、まぁ間違わないでしょう。 ただ、第7引数、第8引数にあたりになると、どっちに「星座」で、どっちに「好きな食べ物」設定するんだ?ってなる。

// 新規のユーザを作成
var user = new User('数多の世界を救済した勇者 ああああ', 60, 'XXX-XXXXX', '勇者の城(旧魔王の城)', 'XXX-XXXX-XXXXX', 'AB', '乙女座', '牛ヒレ肉とフォアグラのロッシーニ');

// ↑ こんなに順番覚えていられない。やってられっかばーか ってなる。
このコードの悪いところ (2つめ)

「名前」と「好きな食べ物」だけ設定したい場合も第2引数〜第7引数を指定しなければならない。 コードにすると以下のようになる。

// 新規のユーザを作成
var user = new User('数多の世界を救済した勇者 ああああ', undefined, undefined, undefined, undefined, undefined, undefined, '牛ヒレ肉とフォアグラのロッシーニ');

// こんなの絶対おかしいよ

Builder パターンを使用した例

Builder パターンを使用して、以下のようにコードを改修した。

/**
 * ユーザクラス
 * @param {Builder} builder 
 */
var User = function (builder) {
    'use strict';
    this.name = builder.name;
    this.age = builder.age;
    this.postalCode = builder.postalCode;
    this.address = builder.address;
    this.phoneNumber = builder.phoneNumber;
    this.bloodType = builder.bloodType;
    this.constellation = builder.constellation;
    this.favoriteDish = builder.favoriteDish;
};

User.prototype.toString = function () {
    'use strict';
    var string = (' 名前: ' + this.name 
        + ' 年齢: ' + this.age 
        + ' 郵便番号: ' + this.postalCode
        + ' 住所: ' + this.address
        + ' 電話番号: ' + this.phoneNumber 
        + ' 血液型: ' + this.bloodType
        + ' 星座: ' + this.constellation
        + ' 好きな食べ物: ' + this.favoriteDish)
        ;
    return string;
};

/**
 * ユーザインスタンスを生成するためのビルダークラス
 */
User.Builder = function () {};

/**
 * 名前を設定します。
 * @param   {String} name 
 * @returns {Builder}
 */
User.Builder.prototype.name = function (name) {
    'use strict';
    this.name = name;
    return this;
};

/**
 * 年齢を設定します。
 * @param   {Number} age 
 * @returns {Builder}
 */
User.Builder.prototype.age = function (age) {
    'use strict';
    this.age = age;
    return this;
};

/**
 * 郵便番号を設定します。
 * @param   {String} postalCode 
 * @returns {Builder}
 */
User.Builder.prototype.postalCode = function (postalCode) {
    'use strict';
    this.postalCode = postalCode;
    return this;
};

/**
 * 電話番号を設定します。
 * @param   {String} phoneNumber 
 * @returns {Builder}
 */
User.Builder.prototype.phoneNumber = function (phoneNumber) {
    'use strict';
    this.phoneNumber = phoneNumber;
    return this;
};

/**
 * 住所を設定します。
 * @param   {String} phoneNumber 
 * @returns {Builder}
 */
User.Builder.prototype.address = function (address) {
    'use strict';
    this.address = address;
    return this;
};

/**
 * 血液型を設定します。
 * @param   {String} bloodType 
 * @returns {Builder}
 */
User.Builder.prototype.bloodType = function (bloodType) {
    'use strict';
    this.bloodType = bloodType;
    return this;
};

/**
 * 星座を設定します。
 * @param   {String} constellation 
 * @returns {Builder}
 */
User.Builder.prototype.constellation = function (constellation) {
    'use strict';
    this.constellation = constellation;
    return this;
};

/**
 * 好きな食べ物を設定します。
 * @param   {String} favoriteDish 
 * @returns {Builder}
 */
User.Builder.prototype.favoriteDish = function (favoriteDish) {
    'use strict';
    this.favoriteDish = favoriteDish;
    return this;
};

/**
 * ユーザインスタンスを生成して返します。
 * @throws {Error} 
 * @returns {User} 
 */
User.Builder.prototype.build = function () {
    'use strict';

    if (!this.name) {

        throw new Error('必須項目[名前]が未設定です。');
    }

    return new User(this);
};


var userBuilder = new User.Builder();
var user;
userBuilder
    .name('数多の世界を救済した勇者 ああああ')
    .age(60)
    .address('勇者の城(旧魔王の城)')
    .phoneNumber('XXX-XXXX-XXXXX')
    .postalCode('XXX-XXXXX')
    .favoriteDish('牛ヒレ肉とフォアグラのロッシーニ')
    .constellation('乙女座')
    .bloodType('AB')
    ;
user = userBuilder.build();
ポイント

setter的なメソッド ↓ で builder 自身を返しているところ。

/**
 * 好きな食べ物を設定します。
 * @param   {String} favoriteDish 
 * @returns {Builder}
 */
User.Builder.prototype.favoriteDish = function (favoriteDish) {
    'use strict';
    this.favoriteDish = favoriteDish;
    return this;
};

これにより、jQueryメソッドチェーンとか、Java の StringBuilder の append("~").append("~~~~~").append("") みたいに書けるようになる。イケメン。

改修前のコードの問題が解決されているか

改修前のコードの以下の問題が解決できているかみてみる。

  • 引数の順番を覚えておかないといけない
  • 設定不要なパラメータも指定しなければいけない
var userBuilder = new User.Builder();
var user;

// 各属性を設定する場合、その属性に設定するためのメソッドを呼べばよいため、
// 順番をきにする必要はなくなっている。


// また、設定したくない属性がある場合、
// その属性を設定するためのメソッドを呼ばなければよいため2つ目の問題も解決されている。

userBuilder
    .name('数多の世界を救済した勇者 ああああ')
    .age(60)
    .address('勇者の城(旧魔王の城)')
    .phoneNumber('XXX-XXXX-XXXXX')
    .postalCode('XXX-XXXXX')
    .favoriteDish('牛ヒレ肉とフォアグラのロッシーニ')
    .constellation('乙女座')
    .bloodType('AB')
    ;
user = userBuilder.build();
結論

やっぱりBuilderパターンってすげーや。

HTML5プロフェッショナル認定試験レベル2受験の際に俺が参考にした本と感想とか

今回は半年くらい前に受験した HTML5 プロフェッショナル認定試験 Level2 について。

レベル1については前回の記事で書いているので、そっちで。

jbelltree.hatenablog.com

結果

1発合格でした。が、正答率は、たしか 75% くらいで、わりとギリギリ合格だったはず。 時間的には余裕をもって見直す時間もあったと思う。

試験内容

HTML5プロフェッショナル」とか言ってるけど、レベル2の試験問題は、ほぼほぼ JavaScript です。 HTML5で追加されたAPIの使用方法の問題が大半で、レベル1の問題のような、HTMLタグの書き方とか順番とかの問題はほとんど出題されないです。 詳しくは、公式の出題範囲を。

html5exam.jp

受験対策として使用した参考書

まずメインで使用した参考書 レベル1では紙の書籍を購入したが、レベル2ではkindle版を使用。 amazon の評価は低いけど、自分はこの本をメインで使用して合格しました。 この本の最後にある模擬試験を中心に勉強した。

www.amazon.co.jp

もう一冊、こちらは紙の書籍を購入。 ただし、内容的には上の本の方が詳しく書かれている気がする。 amazon のレビューにもある通り、かなーり簡単に、さらっとJavaScriptを解説しています。 こちらは各章ごとに演習問題がついている。が、解説もあっさり気味。

www.amazon.co.jp

参考にしたWebサイト

レベル1の時と同様、公式サイトにも例題があります。 この例題も2、3回繰り返し解きました。 これから受験する人は、この問題も絶対やっておくべき。

html5exam.jp

あとは、出題範囲に含まれる SVG 関連で、以下のサイトの SVG についてのページも参考になった。あとイラストが可愛い。 (左側メニューの 「SVG(Scalable Vector Graphics)」→「SVGってなあに?」)

たのしいXML: XML/XHTML入門ページです

感想とか

自分は元々 JavaScript が好きな人間なので、勉強していて楽しかったです。 ぶっちゃけ、Geolocation API とか試験対策の勉強しなければ、ずっと知らないままだったし。

あと、結構ちゃんとJavaScriptの言語仕様とかも出題範囲に含まれていて、

// 以下の処理でそれぞれ何が出力されるか答えろ

console.log( false == 0 );

console.log( false === 0 );

みたいな問題も出題されるので、(ちなみに上は true が出力されて、下は false が出力される。)細かいところをおろそかにしていると、わりとしねるなーって思いました。

まぁ、なんか Web の技術が好きで、なんか資格とりたいなーって人には向いてる資格なのかなーって思いました。少なくとも俺は勉強になりました。まる。