2015年9月8日火曜日

コミット・メッセージには気をつかっていますか?

コミット・メッセージには気をつかっていますか?
1か月も経てば、いや、1週間程度でほとんど記憶も吹っ飛び、自分が書いたメッセージさえ意味がわからないなんてことになっていませんか?
たとえば、Git界隈では、このあたりも積極的に議論が成され一定の規範に則って運用しようという文化が醸成されつつあります。
調べてわかればよい、という意見も多く聞かれますが、果たしてこの感覚は正しいものでしょうか?
いえ、正しい誤りという二律背反的な捉え方は無意味でしょう。 第一、時間の無駄です。調べるという行為には追跡という要素があります。この追跡という行為には推測という要素がつきものです。つまり、推測に誤りがあれば間違った情報や解釈に到達してしまう危険性があります。
たかが、コミットメッセージだけで大げさな… という見方もできるかもしれません。事はコミットメッセージだけに留まらずドキュメントやコードにまで影響するのです。

どういうことか?
コミットメッセージさえ気を使えなければ、ドキュメントもまたしかりだと思います。
これは作業品質の問題です。 あるいは、余計なことに頭を使う必要がなければ、もっと本質的な部分に注力することが可能になります。

2015年9月5日土曜日

boot2dockerを試す

WindowsやOSXな方は、boot2docker を導入することで、手軽に Docker のソリューションを試してみることができます。
とは言え、それなりにハマりどころが存在するのも、この手の技術の常です。

まずはインストールしてみましょう。
公式サイトに行って自身の環境にあった boot2docker のインストーラをゲットします。
インストール自体は非常にシンプルで、指示に従うのみです。
その際、VirtualBoxとcygwinもいっしょにインストールされますが、既に導入済みのかたはチェックを外せばいいでしょう。

さて、VirtualBox で 32 bit の仮想サーバーしか作れない、というトラブルに見舞われたなら、BIOSをチェックしてみてください。
VT-x が BIOS で OFF になっているケースが考えられます。

ということで、boot2docker のインストールが完了しました。デスクトップにあるアイコンをダブルクリックすると Dockerコンソールが起動します。このとき、コマンドプロンプトで入力待ち状態になります。これで boot2docker が起動しました。

バージョンを確認してみます。
docker -v

Docker Version 1.8.0. build 0d03096

と表示されれば正常です。

では、早速 Docker を作成します。
たとえば、
docker pull centos:latest

CentOSの最新イメージを取ろうと思います。

と、Pulling repository docker.io...
となったところで、connection refused.

ん。。。

DNSの指定をチェックします。

$ boot2docker ssh
docker@boot2docker:~$ vi /etc/resolv.conf

## そして、以下を追加して
## nameserver 8.8.8.8

docker@boot2docker:~$ cat /etc/resolv.conf
nameserver 8.8.8.8
docker@boot2docker:~$ exit
$ boot2docker restart

そして再び Docker pull

超えるべき壁は多い予感です。

2015年9月3日木曜日

急がば回れ

落ち着きのない仕事をたまに見かけます。というよりかなりの高確率で見かけます。
先を急いでもよいことはありません。

たとえば、ひとつのクラスの実装を終えました。
これから動作させてデバッグをしようと思いますが、果たして、そこで確認をするでしょうか? 再確認です。
クラスを生成してオブジェクト化するにあたり、事前条件は揃っていますか?
実際に動作させた後の事後条件と期待値は頭の中で整理できていますか?
そもそもコードのセルフレビューは実施しましたか?

こういった単純な準備作業は案外重要です。ここで一歩引いて俯瞰するゆとりが、あるのか?ないのか? で時間の節約の仕方がだいぶ変わります。それどころか、この段階でつまらないバグはつぶせるはずです。

昔から言い古されている言葉ですが、ゆっくり、落ち着いて、ひとつひとつ確実にこなすのが結局はいちばん早いのです。

2015年9月2日水曜日

ASP.NETのレガシー・マークアップ

ASP.NET4.5 Web APIで構築されたHTMLに対して Angular.JS でバリデーションをレンダリングしようと企てたのだが、form要素のname属性が捨てられていることに、いまさらながらに気づいた。
下記は MSDN の ASP.NET と XHTML というドキュメントからの抜粋。

---

XHTML に準拠するための ASP.NET 機能 
ASP.NET は、form 要素に action 属性を動的に追加します。既定では、form 要素には XHTML 1.0 Transitional 仕様で許可されている name 属性が含まれています。これ により、フォーム名を使用して form 要素を解決するクライアント スクリプトに依存する既存のアプリケーションとの下位互換性が保持されています。 
メモ : 
form 要素の name 属性は XHTML 1.1 ガイドラインでは許可されていません。name 属性をレンダリングしないようにアプリケーションを構成できます。 

ASP.NET ページとコントロールの XHTML レンダリングの制御 
ASP.NET コントロールで XHTML 1.1 仕様のより厳密な形式でマークアップをレンダリングすることが必要な場合があります。既定のレンダリングには、XHTML 1.1 仕様に 準拠していないマークアップも含まれています。たとえば、XHTML 1.1 標準では、HTML form 要素の name 属性の使用は禁止されています。 
メモ : 
レガシ マークアップをレンダリングするオプションは、主に既存のページを ASP.NET の最新バージョンに移行するために提供されているので、ASP.NET の将来のバージョ ンではサポートされなくなる可能性があります。 

レガシ レンダリング 
レンダリングをレガシに設定すると、ASP.NET のページとコントロールは、レンダリング機能を ASP.NET の以前のバージョンの動作に変更します。次のような変更が行われます。 
form 要素は、name 属性を使用してレンダリングされます。

---

以上を踏まえてASP.NETのマークアップを利用してレンダリングするには、次の3つの方法がある。

・Legacy (以前のバージョンの ASP.NET でのマークアップのレンダリング方法とほぼ同じ、典型的な例は、form タグの name 属性をレンダリングする場合)
・Transitional (XHTML 1.0 Transitional)
・Strict (XHTML 1.0 Strict)

どの方法を使ってレンダリングするかは、以下の方法で指定する。
Web.config ファイルの system.web 要素に xhtmlConformance 要素を追加する。次に、mode 属性を Legacy、Transitional、または Strict に設定する。

xhtmlConformance 要素が Web.config ファイルに定義されていない場合、既定の設定モードは transitional となる。

以下は、XHTML のレンダリングを無効にするコード例

<system.web>
<!-- other elements here -->
    <xhtmlConformance
        mode="Legacy" />
</system.web>

以下は、XHTML 1.0 Strict のレンダリングを指定するコード例

<system.web>
<!-- other elements here -->
    <xhtmlConformance
        mode="Strict" />
</system.web>

では、Legacyレンダリングに設定した場合の副作用は・・・
1)form 要素の内部の div 要素はコントロールのコンテナとして自動的にレンダリングされない
2)検証コントロールは、controltovalidate などのカスタム属性を使用して span 要素としてレンダリングされる
3)img 要素では、alt 属性と src 属性はそれらを明示的に含めない限りレンダリングされない
4)Autoポストバック機能をサポートする必要がある場合、コントロールは language="javascript" などの language 属性をレンダリングする。
5)コントロールの Wrap プロパティが false に設定されている場合、div 要素をレンダリングする Panel などのコントロールに nowrap 属性が追加される
6)ImageButton コントロールは、border 属性をレンダリングする
7)br 要素は、すべて <br> としてページにレンダリングさる。ただし、明示的に <br /> タグを記述すると、そのままレンダリングされる。
8)BackColor プロパティが設定されている場合、DataGrid コントロールと Calendar コントロールには、レンダリングされた table 要素に bordercolor 属性が含まれる

以上は押さえておくべきポイントです。

2015年9月1日火曜日

gulpモジュールで簡単なタスク自動化

gulp は Node.js 上で動作するタスク自動化のためのビルドツールです。
ソースファイルの圧縮、lessファイルのコンパイルやCSSのベンダープレフィックスの付与、CoffeeScriptのコンパイルなどを実行できます。
タスク定義をシンプルな JavaScript で記述して動作させるのが特徴です。このあたりが Grunt のJSONで宣言的に定義する方法より細かい制御がシンプルに記述できる理由です。

では gulp をインストールしてみます。今回はWindowsで試してみます。
まずは npm で gulpモジュール をグローバルオプションでインストールします。
npm install -g gulp

C:\Users\username\AppData\Roaming\npm\node_modules\gulp\bin\gulp.js
gulp@3.9.0 C:\Users\username\AppData\Roaming\npm\node_modules\gulp
├── pretty-hrtime@1.0.0
├── interpret@0.6.5
├── deprecated@0.0.1
├── archy@1.0.0
├── tildify@1.1.0 (os-homedir@1.0.1)
├── minimist@1.2.0
├── v8flags@2.0.10 (user-home@1.1.1)
├── chalk@1.1.1 (supports-color@2.0.0, escape-string-regexp@1.0.3, ansi-styles@2.1.0, strip-ansi@3.0.0, has-ansi@2.0.0)
├── semver@4.3.6
├── orchestrator@0.3.7 (sequencify@0.0.7, stream-consume@0.1.0, end-of-stream@0.1.5)
├── liftoff@2.1.0 (extend@2.0.1, rechoir@0.6.2, flagged-respawn@0.3.1, resolve@1.1.6, findup-sync@0.2.1)
├── gulp-util@3.0.6 (array-differ@1.0.0, array-uniq@1.0.2, lodash._reevaluate@3.0.0, lodash._reescape@3.0.0, beeper@1.1.0, object-assign@3.0.0,  lodash._reinterpolate@3.0.0, replace-ext@0.0.1, vinyl@0.5.1,lodash.template@3.6.2, through2@2.0.0, multipipe@0.1.2, dateformat@1.0.11)
└── vinyl-fs@0.3.13 (graceful-fs@3.0.8, strip-bom@1.0.0, defaults@1.0.2, vinyl@0.4.6, mkdirp@0.5.1, through2@0.6.5, glob-stream@3.1.18, glob-watcher@0.0.6)

任意のディレクトリに再度gulpモジュールをインストールします。
これは、グローバルでインストールした gulp がローカルインストールの gulp を実行する役割に使われるためです。
プロジェクトによって gulp のバージョンを合わせることなくタスクを実行できます。
npm install gulp

また、以下のようなオプションでインストールすると package.json で管理できるようになります。
これは、プロジェクトメンバ間でパッケージモジュールそのものを管理するのではなく、package.json を基にして、その都度インストールするときに便利です。
npm install --save-dev gulp

バージョンを確認します。
gulp -v
[23:05:23] CLI version 3.9.0
[23:05:23] Local version 3.9.0

次に gulpfile.js というファイル名で gulp の設定ファイルを作成します。

'use strict'
var gulp = require('gulp');
 
// 監視タスク
gulp.task('watch', function () {
    gulp.watch('*', function (event) {
        console.log('File ' + event.path + ' was ' + event.type + ', running tasks...');
    });
});
 
// デフォルトタスクとしてwatch
gulp.task('default', function () {
    gulp.run('watch');
});

では、gulpを動作させます。コマンドは次のようにシンプルです。
gulp

[23:15:09] Using gulpfile C:\xxx\Gulp_Test\gulpfile.js
[23:15:09] Starting 'default'...
gulp.run() has been deprecated. Use task dependencies or gulp.watch task triggering instead.
[23:15:09] Starting 'watch'...
[23:15:10] Finished 'watch' after 12 ms
[23:15:10] Finished 'default' after 21 ms
File C:\xxx\Gulp_Test\新しいテキスト ドキュメント.txt was added, running tasks...
File C:\xxx\Gulp_Test\新しいテキスト ドキュメント (2).txt was added, running tasks...
File C:\xxx\Gulp_Test\新しいテキスト ドキュメント (2).txt was deleted, running tasks...
File C:\xxx\Gulp_Test\新しいテキスト ドキュメント (3).txt was renamed, running tasks...
File C:\xxx\Gulp_Test\新しいテキスト ドキュメント (3).txt was deleted, running tasks...
^Cバッチ ジョブを終了しますか (Y/N)? y

任意のディレクトリ配下のファイル変更を監視し、変化があればコンソールにメッセージを表示します。
gulpコマンド実行後、いろいろなファイルを作成して試してみてください。

以上のような特性を利用して、テストランナーを走らせたり、ビルドタスクを実行したりするわけです。

2015年8月31日月曜日

Dockerのデータのポータブル化

Dockerコンテナの永続化についてです。
本来、ポータビリティの高い、あるいは、ポータブル化が主目的であるはずのコンテナでいかに永続化するのか、ある種のパターン化したソリューションの紹介です。

たとえば、MySQLをコンテナとして起動します。コンテナを stop させれば、当然ながら蓄積されたレコードは跡形もなく消えてしまいます。
そこで、よく用いられる手法が、データをホストのディレクトリにマウントする方法。

sudo docker run --name=mysql-data -d -v /opt/data/mysql:/var/lib/mysql foobar/mysql:latest

ボリュームオプションにより、ホストの /opt/data/mysql/ に記録しようと企てています。
しかし、この方法だとコンテナ自体のポータビリティが損なわれ、ほかのホストへの移植に際して考えなければならないことが増えてしまいます。
当然ながら、開発環境とテスト、本番などの差異を吸収するのが困難になります。

そこで、MySQLコンテナとは別にデータを永続化するコンテナを作成する方法をとってみます。
Dockerfileを作成します。
今回は最小限の構成で作成されている公式のイメージ busybox を使用します。

FROM busybox
VOLUME /opt
CMD /bin/sh

このDockerfileをビルドします。
$ sudo docker build -t foobar/mysql-storage:1.0 /opt/data/mysql

完了したら sudo docker images で確認します。

次に永続化用データコンテナを起動します。
$ sudo docker run -i -t -v /opt --name mysql-data busybox /bin/sh

ボリュームオプションで /opt以下を格納するコンテナになります。

では、このコンテナを使う側から見ます。
$ sudo docker run -t -i --volumes-from mysql-data mysql /bin/bash
--volumes-fromで件のコンテナのディレクトリを参照して起動します。これで件のコンテナとつながりました。

/opt 以下が接続されたのか確認します。
/# ls -al /opt/

本来のマイクロサービス、あるいは、一定の粒度をもったSOAアーキテクチャの設計パターンでは、このような Dockerソリューションの隔離されたうま味を十分に生かせるような発想が重要になってくるはずです。

2015年8月29日土曜日

Expressであえて静的なファイルを生成してみる

たとえば、以下の2種類のJade定義を用意します。

1) base.jade:

doctype html
html
  head
    title= title
    link(rel='stylesheet', href='/stylesheets/style.css')
  body
    block content

2) extend.jade:

extends base

block content
  h1= title
  p Welcome to #{title}

これは、2)のHTML出力用に定義した extend.jade をテンプレートとして、これから HTML を生成しようと思います。
しかし、上記には構造上のちょっとした工夫があって、extend.jade は、1)の base.jade を継承しています。
具体的には、おおまかなレイアウトは base.jade が担い、body の部分を extend.jade に差し替えています。
それが、block content という記述です。

さらに、Nodeのほうでは、HTML をレンダリングするのではなく静的な HTML ファイルを物理的に生成しようと思います。
それが次のコードです。

まずは、ルーティングの部分にRESTのPostリクエストを、app.js に記述します。
var output = require('./routes/output')
app.use('/output/:param', output);

次に処理の部分を output.js に記述します。
var express = require('express');
var router = express.Router();

var jade = require('jade'),
    fs = require('fs');

/* POST listing. */
router.post('/', function (req, res) {

  // 事前条件は省略 ・・・

    fs.readFile('./views/extend.jade', 'utf8', function (err, source) {
        if (err) throw err;
        console.log(source);
        var opts = {
            pretty: true, filename: './views/base.jade'
        };
        var template = jade.compile(source, opts);
        html = template(body);
        fs.writeFile('./public/test_file.html', html);
    });

  // レスポンス処理は省略 ・・・
});

module.exports = router;


通常、このようなコードを書くことはないと思いますが、実験です。あえて静的なHTMLをレンダリングするのではなく実体を出力します。
ポイントは、jade.compile() の第2引数として与える opts のパラメータに jadeの継承元のファイルを指定してあります。

では、POSTでリクエストします。URLはこんな感じです。当然 JSONプロトコルです。
http://XXX.XXX.XXX.XXX:YYYY/output/param

そして body はこんな感じ。
{
  "title": "test_parameter"
}

生成された HTML ファイルは以下のようになります。
<!DOCTYPE html>
<html>
  <head>
    <title>test_parameter</title>
    <link rel="stylesheet" href="/stylesheets/style.css">
  </head>
  <body>
    <h1>test_parameter</h1>
    <p>Welcome to test_parameter</p>
  </body>
</html>

という検証結果でした。
今回はノンブロッキングIOに関する考察は省略しましたが、この部分は注意してください。