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

Perlにおける日本語文字化け対策の私的まとめ

perl

Perlで日本語のテキストを処理しているとけっこうな割合で文字化けにハマる。
近いことについては以前ここでみっちり書いたが、
note103.hateblo.jp
どうもその後、自分はbinmode関数やopen関数、およびutf8やopenプラグマについて理解が怪しいな、と思ったのでいろいろ調べつつ現時点での認識をまとめてみる。

環境づくり

まずはサンプルケース的に、文字化けしがちな状況を作る。

素材データとして、以下の内容をエンコーディングUTF-8のテキストファイルにsource.txtという名前で保存。

りんご
hello

1234
ネコ

次に、そのデータをopen関数で読み込み、split関数で切り刻んで標準出力および書き込み用ファイルresult.txtへ書き込むPerlスクリプト「openio_stdout.pl」を書く。

#!/usr/bin/env perl
#
# openio_stdout.pl

use strict;
use warnings;
use feature 'say';

use utf8;
use open IO => qw/:encoding(UTF-8)/;
binmode STDOUT, ':encoding(UTF-8)';

# 1. 素材データ読み込み
my $in = 'source.txt';
open my $fh, '<', $in or die $!;
    my @data = <$fh>;
close $fh;

# 2. いろいろ処理
my @out;
for (@data) {
    my @split = split//, $_;
    for my $s (@split) {
        push @out, "字$s";
    }
}

# 3. 処理済みデータを書き込み
my $out = 'result.txt';
open $fh, '>', $out or die $!;
    print $fh @out;
close $fh;

# 4. 標準出力に出力
print @out;

実行。

字り字ん字ご字
字h字e字l字l字o字
字犬字
字1字2字3字4字
字ネ字コ字

素材テキストの1文字ずつの間に「字」を入れてみた。
これが書き込み先のresult.txtにも、標準出力(ターミナル)にも出ている、という状況。

つまり、この時点では文字化けしていない。が、それは冒頭にある以下の宣言がちゃんと動いているからで、

use utf8;
use open IO => ':encoding(UTF-8)';
binmode STDOUT, ':encoding(UTF-8)';

これを誤るとけっこう盛大に文字化けする。
以下、それを順に見ていく。

utf8プラグマ

まず、今回の例ではソースコード内に日本語の文字(「字」)を入れているので*1、最初のutf8プラグマが必要になる。

use utf8;

もしこれをコメントアウト等で無効にすると……

f:id:note103:20160925140246p:plain

こんな感じになる。
標準出力でも、書き出しファイルでもこうなる。

utf8プラグマというのは、この例における「字」のように、ソースコード内に素材となる文字を直接書いたとき、それをPerlで処理するための「内部文字列」に変換してくれるもの。

内部文字列に変換されなかったらどうなるかと言うと、Perlがそれを「なんか文字じゃないもの」ぐらいにしか扱ってくれず、上の画像のように化けてしまう。

ちなみに、この「内部文字列に変換されなかった何か」のことは外部文字列……とは呼ばず、「バイト列」と呼ぶことが多いらしい。

で、ここではそのコード内に直接書かれた「字」をutf8プラグマの宣言によって「内部文字列」に変換している。

openプラグマ

次に、このコードではファイル入出力(source.txtを読み込んでresult.txtに書き込む)をやっているので、2番めのopenプラグマも必要になる。

これは別解として、各open関数の第2引数でこのように書いても良いようで、

open my $fh, '<:encoding(UTF-8)', $in or die $!;
(略)
open $fh, '>:encoding(UTF-8)', $out or die $!;
(略)

それを冒頭のプラグマでまとめて宣言している。

また、このプラグマ部分はこのように分けて書くこともできるが、

use open IN => ':encoding(UTF-8)';
use open OUT => ':encoding(UTF-8)';

今回はIN/OUTの両方をやってるのでIOというレイヤーでまとめている。
と同時に、IOなら省略してもOKらしい。

use open ':encoding(UTF-8)';

で、さっきのutf8プラグマは元に戻して、このopenプラグマだけ無効にするとどうなるかと言うと、こうなる。

f:id:note103:20160925140639p:plain

このうち、上側の

Wide character in print at /Users/kadomatsuhiroaki/open/openio_stdout.pl line 29.

というのは標準出力(ターミナル)に出るもので、書き出し先のファイルには出てこない。

その下の文字化け部分は、標準出力と書き出しファイルの両方に出ている。
不思議なことに、というか特徴的なこととして、一つ前の文字化けでは文字間に挟んだ「字」が化けていたのに対し、今度は「字」だけが普通に表示されている。

この段階ではutf8プラグマが生きていて、openプラグマを止めているのでそういう生死の違いが出るのだろう。

また、openプラグマの引数「:encoding(UTF-8)」は、「:utf8」と書いてもほぼ同等の働きをするようだが、前者はデータの入力時にそれが正しいutf-8かどうかをチェックするのに対し、後者はそうじゃないらしいので少なくとも入力時はあまり省略しないほうが良さそうである。

binmode関数

最後に、binmode関数。じつはこれが今まで一番わかっていなかったのだが、どうもいろいろな現象や解説書を並べて観察してみると、単に(というか)標準入出力時にその対象となるデータの文字コードを指定するもの、と考えれば良さそうである。

今回はデータをファイルから入力して、ファイル&標準出力に出しているので、STDOUT時の文字コードのみをbinmodeで指定している。

binmode STDOUT, ':encoding(UTF-8)';

例のごとく、これだけコメントアウトしてみると……。

f:id:note103:20160925140820p:plain

さっきと同じ。……かと思いきや、また微妙に違っていて、まず以下の対象行番号が29から33に変わっている。

Wide character in print at /Users/kadomatsuhiroaki/open/openio_stdout.pl line 33.

ではこの二つの行がソースコード上のどこにあたるかと言うと、以下の部分における、

# 3. 処理済みデータを書き込み
my $out = 'result.txt';
open $fh, '>', $out or die $!;
    print $fh @out;
close $fh;

# 4. 標準出力に出力
print @out;

前者のprint文が29行目で、最後のprint文が33行目。

つまり、openプラグマはopen関数内のprint文に効いていて、binmode関数の方は標準出力時に影響していることがこれらの情報から見てとれる。

また、肝心の本文のほうも、前者は文字化けしているが後者はしていない。
ただしこれは、ここで問題にしているbinmode関数の有無による違いではなく、ひとつ前の例でopenプラグマをコメントアウトした際、入力レイヤー(IN)も外してしまっているために、前者では文字化けが生じていると考えられる。

試しに、一つ前の文字化けはこのような状態で生じたが、

# use open IO => ':encoding(UTF-8)';
binmode STDOUT, ':encoding(UTF-8)';

このように、その状態からopenプラグマの入力レイヤーだけを復活させると、

use open IN => ':encoding(UTF-8)';
binmode STDOUT, ':encoding(UTF-8)';

文字化けは解消する。
(と言いつつ、たしかに文字化けは消えるが今度はbinmode関数のみを無効にした場合とは少し異なるエラーが出てくる。つまり、それらはどれも異なる状態なのだが、これ以上の追求&説明はだいぶ大変なので割愛)

標準入出力もopenプラグマにまとめる

今回の研究というか勉強に際しては、以下3冊を繰り返し見比べては突き合わせ、読み返したが、

初めてのPerl 第6版

初めてのPerl 第6版

かんたん Perl (プログラミングの教科書)

かんたん Perl (プログラミングの教科書)

Perl CPANモジュールガイド

Perl CPANモジュールガイド

そのうちのCPANモジュールガイドで紹介されていた方法。

現在はこのようにしている2行を、

use open IO => ':encoding(UTF-8)';
binmode STDOUT, ':encoding(UTF-8)';

以下のようにまとめられる。

use open IO => qw/:encoding(UTF-8) :std/;

ようはbinmode関数で指定していたことをopenプラグマの引数に「:std」とすることで代替(というか)できる。

いま自分で書いているコードにおいては、同様のことをしたいときは基本最後の形にしている。

まとめ

日本語の文字化けについては常に悩まされるところだが、原因を追っていくとそれなりに明らかになってくるのが面白い。

エラーの内容も書き換えた部分によって変わってくるし、同じエラー・メッセージでもその分量(行数というか)が異なり、それがまたマシンの気まぐれなどではなく、異なるには異なるだけの理由がある。

面倒だ、ぐぬぬ、イライラする! と思うことも少なくはないが、それでも玉ねぎの薄皮を剥がすように少しずつマシになってきていると感じる。
そのような理解を助けてくれる上述の書籍、および知見に満ちた先達やネット上の各種解説記事に感謝します。

付録

今回の出力例の画像(黄色っぽいベージュっぽいやつ)について、本来ターミナルに出るような結果なのに行番号が出ているのはなぜだろう? と思われる人もいるかもしれないが、これはコードの実行結果をVimの同一ウィンドウ&分割バッファで表示してくれるプラグインquickrun.vim」を使って表示している。
github.com

ここでやっているような利用法については以下の記事でも触れたので合わせて挙げておく。
note103.hateblo.jp

*1:サンプルの文字選択を誤ったかもしれない。まぎらわしい。

Perlのオブジェクト指向をつかんだ

perl oop

経緯

2013年の春にふと「よし、プログラミングやろう」と決めてその夏にYAPC::Asiaに参加して、その直後に買ったのが以下の本。

すぐわかる オブジェクト指向 Perl

すぐわかる オブジェクト指向 Perl

たしか同YAPCDeNAの人が大規模新人研修に関する発表をしていて()、その最後のほうでお勧め入門書ベスト5みたいなやつを紹介していたのだけど、それがよくある特定の選者が一括で選ぶようなものではなく、研修を受けた側の新人さんたちに聞いたアンケートから抽出されたというリアルなもので、そこに含まれているのを見て興味を持った。

で、先日ようやくそれを読み終わって出た感想。


かるくタイポしてるが、

s/年前/年/

実感的にはほんとに「ようやくつかんだ〜」という感じだった。

オブジェクト指向というと、よく「理解は容易だが運用は難しい」という、なんだかスクラム実践入門みたいなことを言われるわけだが、ぼくはその前者の「理解」の段階だけで3年かかってしまった。

まあ、3年ずっとべったり学習し続けてその間わからなかった、ということでもないのだが(読んでない時間の方が多い)、ともあれ、たしかにわかってみると(あるいはそのような気になってみると)「理解は容易」と言われるのもわかる気はする。シンプルといえば大変シンプルなものである。

またオブジェクト指向といえば、「データと処理をセットで扱うものである」なんていうこともよく言われる。これもとくに理解してない段階で聞くと「はあ、そんなものですか」という感じだが(日本語としては理解できる、というか)、今になって思えば、その辺に関する「わかる/わからない」を分けるのは、概念を聞いて理解できるかどうかということではなく、具体的なコードをどれだけ見たか、書いたか、実行したかによって変わってくるように思える。
つまり、パッと聞いてわかるとかそういうものではなさそう。(あくまで入門者に関して言えることだが)

ひと口にオブジェクト指向と言っても、JavaRubyPerlのそれぞれでは、元になる概念に共通する面はあっても、やはりコード上ではそれなりに違いがあるだろう。
そこには、単に構文上の違いだけではなく、お作法というか慣習的な面で、「こうするのがヨイとされている」みたいな違いもあるはずで、だから結局は自分が普段よく使う言語を通してそれを学ぶのが、一番の理解の近道になるのではないかとも感じる。

冒頭の本の話に戻ると、これはけっこうなページ数と文章量があるうえ、大判のせいかやけに重たいので(質量が)、最後まで読むのはけっこう骨が折れた。
ちょっと時間ができたからといって、棚からそれを出すのも大変だし、開いて読むにもちょっとしたスペースが必要だしで、気持ちの面である程度余裕がないと「さあ、読もう」という感じになれない。

もしこれが多少なり素地のある人なら、自分のわからない/知らない部分だけを補う用途で日常的に付き合えるかもしれないが、ぼくの場合はそれこそある程度べったり読み込まないと解読できない内容だったので、その「腰を落ち着けて取り組む機会」をなかなか作れず挫折していた、というのもある。

ちなみに、同書の紹介としては小飼弾さんの以下が大変参考になって、コメント欄では著者の深澤さんもいろいろ述べておられて面白いのだけど、

404 Blog Not Found:$this->get if $you->learn(slow) - 書評 - すぐわかるオブジェクト指向Perl

そこでも言われているように、ほんとに「じっくり、ゆっくり、時間をかけて」という感じで読み継いだ。

じつは同書の前半には、非オブジェクト指向ネタというか、リファレンスに関する説明がみっちり載っていて、購入してから1〜2年ほどは、どちらかというとそのリファレンスまわりの理解を深めるために読むことが多かった。

というか、もちろん最大の目的はその時点でもオブジェクト指向だったので、そっちも読もうとはするのだけど、やはりその辺ってそこまでの前半部分を読んでいる前提で解説されているので、後半だけ読んでもまったく頭に入らず、それで前半に戻ってリファレンスのところなどを一生懸命読み返す、というのがしばらく続いた。

ちなみに、そのリファレンスまわりの解説について言えば、本書ほど丁寧にPerlのリファレンスについて教えてくれる入門書はない(おそらく今後も)だろうと思っている。
もし今つまづいている人がいたらお勧めしたい。

さて、とはいえそんな調子でのったらのったら読んでいるので、後半のオブジェクト指向にはいつまでも入れず、また普段からあまり余裕がなくて本自体にもなかなか触れられず、触れられないうちに前に読んだところも忘れて、だからようやく読み返したときにはまた最初のほうから読み直して……とかやってるうちに「もうこれ、最後まで読み切ることはないかもなあ」という諦め気分だったのだけど、なぜか今年の夏に入ったあたりで、「やっぱり……次はオブジェクト指向だな」と思った。

というのも、オブジェクト指向を多少なり理解していないことには、読めない他人のコードというのが多すぎると感じたのだ。
これは少し前にC言語の学習を始めたことや、シェルスクリプトLinuxコマンドを学びはじめたことにも近い理由であって、言い換えれば「みんなこの言葉を喋っているので自分も学ばないと彼らが何言ってるのかいつまでもわからないぞ」という焦りの気分でもある。

ということで、じゃあどこから再入門するかと思ったとき、半ば挫折しかけてはいるとはいえ、とりあえず途中までは読んでいる同書に再度取り組みはじめたら、ある程度心が決まっていたせいか最後まで理解しつつ読み終えることができたという話。

概念

ということで、以下ではここまでに理解した内容を簡単にまとめてみたい。

まず、オブジェクト指向を一言でいえば、上でもちらっと書いたように「データ(属性・プロパティ)と処理(振る舞い・メソッド)をくっつけたオブジェクトなるものを使っていろいろやる」ということになる。
この概念が、この話の一番の軸・前提になる。

また、Perlを使ったオブジェクト指向においては、おもに前者のデータをリファレンスで、後者の処理をサブルーチンで表す。
で、作ったそれらをbless関数でくっつけるとオブジェクトができる。

ここで出来たオブジェクトというのは、鋳型(いがた)のようなもので、鯛焼きやタコ焼きで使うような、型のある鉄板みたいなもの。
と同時に、プログラムの中で実際にあれこれやるのはその型じたいではなく、型をもとに作られた鯛焼きなりタコ焼きなりの1個1個。

で、前者の鋳型みたいなものをクラスと言い、その鋳型から出てきた後者の1個1個の具体的な実体をインスタンスと言う。

そしてその1個1個に対して何かを入れたり、そこから何かを引き出したり、それに何かをやらせたりしていく中でいろいろやるのがオブジェクト指向プログラミング。(雑になってきた)

実例

では概念的な話はそのぐらいにして、以下ではPerlによるそれを実例で紹介してみる。
むちゃくちゃベタだけど、動物ネタで。

こんな感じの構成を考える。

Animal
    ├─ lib
    │    ├─ Animal.pm
    │    └─ Animal
    │           ├─ Dog.pm
    │           └─ Cat.pm
    └─ main.pl

これはざっくり言うと、Animalという型が元にあって、それを継承したDog, Catという子クラスを配置したモデル。

いまあっさり「子クラス」と書いたが、そのときAnimal.pmの方は「親クラス」ということになる。

が、それは説明が簡単なのでそのように言っているものの、実際にはAnimalとDog/Catの関係は「親/子」とか「主/従」のような上下関係というより、「抽象/具体」という対照的な(お互いに呼応した)関係だと考えたほうが腑に落ちる。
これは冒頭に挙げた深澤さんの本でそのように説明されていて、なるほどと思った。

では具体的なコード。

まずAnimal.pm。

package Animal;
use strict;
use warnings;

sub new {
    my $class = shift;

    my %self = @_;
    $self{name} //= 'No name';
    $self{age} //= 0;
    $self{sound} //= '(silence)';

    bless \%self, $class;
}

sub speak {
    my $self = shift;
    return $self->{ sound };
}

1;

newメソッドの中でプロパティ(属性)を設定している。この「プロパティ」というのは他にも「アトリビュート」とか「フィールド」とも呼ばれるようだが(後者はJava用語っぽい)ここではプロパティと呼んでおく。

speakというのはサブルーチンだが、オブジェクト指向の際にはメソッドと呼ぶらしい。

上のほうで「データと処理」と表現したが、先のプロパティがデータにあたり、このメソッドが処理にあたる。

次に、Animal.pmを継承したDog.pm。

package Animal::Dog;
use strict;
use warnings;
use parent 'Animal';

sub speak {
    my $class = shift;
    return 'Bow!';
}

sub move {
    my $class = shift;
    return 'Jump!';
}

1;

継承すると、親クラスのAnimalの方で定義しているメソッド(newやspeak)を子クラスでも使えるようになる。だからここではnewメソッドを作らない。

なるほど、これなら重複する内容を書かなくて済むわけで、継承などをしない手法に比べて大きなメリットだと感じる。

その上で、ここではメソッドのオーバーロード(上書き)というやつで、speakメソッドをAnimal.pmのそれからちょっと書き換える。
Animalのspeakメソッドではプロパティ内のsound要素を呼び出していたが、Dogの方ではそうせずに独自の 'Bow!' を返すことにする。

また、Animalの方にはなかったmoveメソッドも独自に追加した。

もう一個、Animal.pmを継承したCat.pmを作ってみる。

package Animal::Cat;
use strict;
use warnings;
use parent 'Animal';

sub new {
    my $class = shift;
    my %self = @_;
    $class->SUPER::new(%self, sound => 'Nyaa..');
}

1;

こちらではnewを少し書き換える。
Dog.pmの方ではspeakメソッドを直接変更したが、ここではnewの方からsoundの値を書き換えて鳴き声を変えてみる。

この書き換えはあまりいい例じゃない気もするが(有効性を感じられないというか)、まあ、子クラスから親クラスのメソッドを呼び出す例として面白いので。

最後に、それらを実行するmain.pl。

#!/usr/bin/env perl
#
# main.pl

use strict;
use warnings;
use feature 'say';
use lib './lib';
use Animal;
use Animal::Dog;
use Animal::Cat;

my $animal = Animal->new(name => 'foo', age => 100);
say "Animal's name:\t".$animal->{ name };
say "Animal's age:\t".$animal->{ age };
say "Animal speaks:\t".$animal->speak;
say '---';
my $dog = Animal::Dog->new(name => 'Pochi', sound => 'Vow!');
say "Dog's name:\t".$dog->{ name };
say "Dog's age:\t".$dog->{ age };
say "Dog speaks:\t".$dog->speak;
say "Dog moves:\t".$dog->move;
say '---';
my $cat = Animal::Cat->new(name => 'Tama', age => 3);
say "Cat's name:\t".$cat->{ name };
say "Cat's age:\t".$cat->{ age };
say "Cat speaks:\t".$cat->speak;

結果。

Animal's name:	foo
Animal's age:	100
Animal speaks:	(silence)
---
Dog's name:	Pochi
Dog's age:	0
Dog speaks:	Bow!
Dog moves:	Jump!
---
Cat's name:	Tama
Cat's age:	3
Cat speaks:	Nyaa..

OK。

もう一個、オブジェクト指向では多重継承という手法がよく話題になるようで、ここではDogとCatの親クラスはAnimalのみだけど、複数の親からメソッドを継承したい場合にはどうするか、という話。

たとえば、「動物の中の何か」であると同時に、「その物体は何色か」という要素を規定するクラスをDogやCatで共通して流用したい場合。

ひとつの方法として、現在Animalから諸メソッドを継承しているように、そういった別の親クラス(仮にColor.pmとする)を継承しても良いが、多重継承というのはいろいろ煩雑になる面があるらしく(雑な説明だが)、それを避けたい場合は普通にuseする。

まずColor.pmを作る。

package Color;
use strict;
use warnings;

sub color {
    my $self = shift;
    my $color = shift;
    if ($color) {
        return $color;
    } else {
        return 'brown';
    }
}

1;

引数を与えたらその色、与えなければ「brown」ということにした。
(たしか「続・初めてのPerl」でこんな例があった気がしたので借りた)

ここではこのColor.pmをAnimal.pmと同階層に置いておく。
こんな感じ。

Animal
    ├─ lib
    │    ├─ Animal.pm
    │    ├─ Color.pm # <= 追加
    │    └─ Animal
    │           ├─ Dog.pm
    │           └─ Cat.pm
    └─ main.pl

で、Animal.pmを少し書き換え。

package Animal;
use strict;
use warnings;

sub new {
    my $class = shift;

    my %self = @_;
    $self{name} //= 'No name';
    $self{age} //= 0;
    $self{sound} //= '(silence)';

    bless \%self, $class;
}

sub speak {
    my $self = shift;
    return $self->{ sound };
}

# colorメソッドを追加。
sub color {
    my $self = shift;
    my $color = shift;
    return Color->color($color);
}

1;

このままDog, Catの方はとくに触らずに、main.plでColor.pmをuseして、それぞれのcolorを呼び出してみる。

#!/usr/bin/env perl
#
# main.pl

use strict;
use warnings;
use feature 'say';
use lib './lib';
use Animal;
use Animal::Dog;
use Animal::Cat;
use Color; # <= 追加

my $animal = Animal->new(name => 'foo', age => 100);
say "Animal's name:\t".$animal->{ name };
say "Animal's age:\t".$animal->{ age };
say "Animal speaks:\t".$animal->speak;
say '---';
my $dog = Animal::Dog->new(name => 'Pochi', sound => 'Vow!');
say "Dog's name:\t".$dog->{ name };
say "Dog's age:\t".$dog->{ age };
say "Dog speaks:\t".$dog->speak;
say "Dog moves:\t".$dog->move;
say "Dog's color:\t".$dog->color; # <= 追加
say '---';
my $cat = Animal::Cat->new(name => 'Tama', age => 3);
say "Cat's name:\t".$cat->{ name };
say "Cat's age:\t".$cat->{ age };
say "Cat speaks:\t".$cat->speak;
say "Cat's color:\t".$cat->color('white'); # <= 追加

結果。

Animal's name:	foo
Animal's age:	100
Animal speaks:	(silence)
---
Dog's name:	Pochi
Dog's age:	0
Dog speaks:	Bow!
Dog moves:	Jump!
Dog's color:	brown
---
Cat's name:	Tama
Cat's age:	3
Cat speaks:	Nyaa..
Cat's color:	white

OK。Dog, Catの最後にカラーが追加された。

このように、「多重継承したいけどしたくないので別の方法でいい感じにいろんなクラスを取り込みたい」みたいな時のこういう方法をMix-inというらしい。
いや、厳密に定義すれば上のような方法をそうは言わないかもしれないが(よく知らない)、まあ理念というか目的としては似たようなものかと捉え中。

参考書籍

ちなみに、そのMix-inを含めてオブジェクト指向の基礎みたいなところについては、まつもとゆきひろさんの以下の本がとても参考になった。(まだ読み切れていないが入門者向けっぽいわりにすごい濃い)

また、同書を紹介してくれたのはYAPC::AsiaやPerl入学式で時々会う人で、「あの本はオブジェクト指向の説明がすごくわかりやすかったな」と、たしか一昨年(2014年)のYAPC::Asiaで会の終了後に会場下のHUBで飲んでいるときに教えてもらったのでそのまま購入&読んだという経緯がある。
その節はありがとうございました。>その方

それから、上でもちらっと書いたとおりオブジェクト指向Perlの学習に際しては、冒頭の深澤さんの本の他、皆さんお馴染み『続・初めてのPerl』と、

続・初めてのPerl 改訂第2版

続・初めてのPerl 改訂第2版

@kaz_hiramatsuさんによる『雅なPerl入門 第3版』が参考になった。
kazhiramatsu.hatenablog.com

どちらかと言うと、『すぐわかるオブジェクト指向Perl』と『雅なPerl入門』で全貌をつかみつつ、『続・初めてのPerl』で脇を固める、みたいな読み方だったか。

まとめ・展望

ということで、本当はこのまま今度は上記のコードをMouseというモジュールを使って書き換えた版も復習がてら書いておきたかったのだけど、だいぶ長くなったのでひとまずここまで。

実際には、これらを踏まえた上で同内容をMouseで書き換えたら「なるほど、まあこの方がいろいろラクかもしれない」と思ったりしたので、そこまでを自分の理解のひとまとまり、と捉えてはいるのだけど。

あと、上では触れなかったがアクセサ(ゲッター&セッター)というやつに関する理解が薄いという自覚があり、かつたぶんカプセル化というやつを意識する上ではそれが重要だと思われるのだけど、その辺の理解度が低い段階で上のようなblessを使った方法でゴリゴリやっているといつまでもこの記事をUPできなそうなので、次にMouseの基礎的な使い方をまとめる際、あらためてその辺も勉強してみたい。

ひとまずのまとめとしては、やはりオブジェクト指向というのはどうもプログラマーの人たちにおける一種の共通言語のようになっている部分があるようで、その一部をカタコトながらも解読できつつあるのは喜ばしい。

同様に、サーバーまわりやSQL、あとちょっと外れたところで(というか)TeXなど*1、勉強したいことは山積みだが地道に触れていってみたい。

*1:自分の分野に近いので、というところもある

GOPATHの設定でハマって解決した話

golang

「みんなのGo言語」が話題だから、というつもりでもなかったのだけど、やはり影響はあるかもしれない。

みんなのGo言語【現場で使える実践テクニック】

みんなのGo言語【現場で使える実践テクニック】

どうもGOPATHというやつの理解がぼんやりしていて、これまでも見よう見まねで設定してはいたのだけど、その足元のおぼつかなさゆえにいつ混乱に陥ってもおかしくないという不安がだいぶ募ってきたので整理と理解を試みた。

けっこう前にセットしてそのままだった.bash_profileを見てみると、こんな風になっていた。

export GOPATH=$HOME/go
export PATH=$PATH:$GOPATH/bin
export GOBIN=$GOPATH/bin

しかしどうもこの最後のGOBINというのは最近見かけない気がするので、いかにも理解してない感じがありそれが怖い。

ということで、とりあえず以前に買って少し読んでいた以下の本を見ながら最新版のGo1.7をMacにインストールし、

スターティングGo言語

スターティングGo言語

そのまま同書の案内にしたがって.bash_profileを以下のように書き換えたのだけど、

export PATH=/usr/local/go/bin:$PATH
export GOPATH=$HOME/go

動かない。

具体的には、第一に毎日毎時間頻用しているmattnさんのchoが動かない。

GitHub - mattn/cho

ぼくは自作のコマンドラインツールでchoをデフォルト的に組み込んでいるので、

choっと作った便利なツール - the code to rock
最近のcarvo: pecoとchoをくっつけた - the code to rock

これにはさすがにゾッとした。ディレクトリ移動、ファイルオープン、不要ファイルの削除などあらゆる面で支障をきたす。

焦りつつ、何がどうなっているのかチェックしてみると、たとえば「$ go get 〜」というふうに外部のパッケージをインストールした際、それがGOPATHで指定した先に入っていくところまでは思惑通り動いているようなのだが、本来ならそれで次の瞬間から有効になるはずのコマンドが効かない。

どうもGOPATHとして設定した「$HOME/go/bin」のバイナリファイルがマシンに認識されていない、無視されている、屍のようだ、という雰囲気を感じる。のだけど、ではそれをどうしたらいいのか……というところで多分4〜5時間ぐらいハマり続けた。

で、結論的にはこれはPATHの設定が駄目で、以下のようにしたら解決した。

export GOPATH=$HOME/go
export PATH=$PATH:$GOPATH/bin

しかしこれ、よくよく見直すと最初の状態に戻っているだけである。

と同時に、なんとなく自分で当たりをつけた原因がそれほど外れていなかったこと、そしてこれまで数年にわたりどうにも理解しきれずにいた「PATHを通す」という言葉の意味の片鱗が、ようやく腑に落ちてきた気もする。

「PATHを通す」という表現をプログラミングの初心者にまともに解説してくれる人や記事にぼくはいまだに出会ったことがほぼないのだけれど*1、自分なりに言い換えれば、それは「最高権力者であるところのマシンが認める限定的な《コマンドファミリー》の一員に入れてやる」というようなことではないかと思い始めている。
(抽象的すぎて初心者にはむしろ不親切な説明だが)

言い換えると、あるコマンド候補生を正式なコマンド集団の一員に昇格させるためにやることは、そいつが今いる場所をその《ファミリー》が支配する新たな縄張りに加えるか、あるいはすでに縄張りになっている場所にそいつを入れるか、そのどちらかであり、通常言われる「PATHを通す」というのは基本的にその前者なのかなと。
(この説明もきわめて抽象的だが)

そのようなことを考えながら上記の失敗例を見直すと、GOPATHの設定とPATHの設定がバラバラで繋がっていない。
懲りずに上の喩えを用いるならば、こちらの意図としてはGOPATH/binの中身をすでに正式なコマンドの一員だと思いこみ周りにもそう吹聴しているのだけど、最高権力者であるところのマシンはそれをまだ《ファミリー》の一員だと認めていない。

これがもし、GOPATHの設定をしないのであればそのPATH設定でもいいかもしれないが、GOPATHを設定する前提ならそのPATH設定のままでは駄目ではないか、と前掲「スターティングGo言語」を何度か読み返しつつ心の中で呟いた。*2*3

ちなみに、PATH設定については以下のように先頭へ代入するよう説明している本や記事もあったが、

export PATH=$GOPATH/bin:$PATH

どうもこうして先頭に入れるというのは、それなりに意味というか必然性がないとちょっと抵抗があるように感じたので、

export PATH=$PATH:$GOPATH/bin

というふうに後に付けるようにしたがそれでとくに問題なさそうである。

というか、こちらのWeb+DBプレスGo特集にもそのように記述されているので大丈夫だろう。

WEB+DB PRESS Vol.82

WEB+DB PRESS Vol.82

  • 作者: 山口徹,Jxck,佐々木大輔,横路隆,加来純一,山本伶,大平武志,米川健一,坂本登史文,若原祥正,和久田龍,平栗遵宜,伊藤直也,佐藤太一,高橋俊幸,海野弘成,五嶋壮晃,佐藤歩,吉村総一郎,橋本翔,舘野祐一,中島聡,渡邊恵太,はまちや2,竹原,河合宜文,WEB+DB PRESS編集部
  • 出版社/メーカー: 技術評論社
  • 発売日: 2014/08/23
  • メディア: 大型本
  • この商品を含むブログ (1件) を見る

というか、このGo特集はその4〜5時間ハマってる間にも何度も目を通していたのだけど、解決した後にあらためて見直したら上記と同じPATH/GOPATH設定の正解がちゃんと載っていて、やっぱり人間、焦ると見落とすな〜とつくづく身に沁みた。

ということで、実りがあるのかどうかよくわからない内容になったが、後になってまた同じようなことで普通にハマりそうなので、そのときの自分のために書いておいた。

追記

「みんGo」のKindle版が出ていたのでサンプルを読んでみたら、第1章の途中まで載っていて好印象*4……と思っていたら上記のGOPATH/GOROOTについても丁寧に触れられており、かつ上記設定で問題なさそうなことを確認できたのでよかった。

みんなのGo言語[現場で使える実践テクニック]

みんなのGo言語[現場で使える実践テクニック]

*1:以前に以下で紹介した「新しいLinuxの教科書」はかなりイイ線行っているが。 http://note103.hateblo.jp/entry/2015/12/17/083000

*2:もしかしたら書中ではきちんと説明されていて、ぼくがそれを見落としているだけかもしれないが。

*3:ちなみに同書じたいはそれこそ初心者向けの丁寧で良いつくりの本だと感じている。

*4:こういったサンプルで前書き&目次までしか載せてないような本も時々あって、売上戦略としては正しいとも感じるが(高額でなければ「本文の方にほしい情報が載っているかもしれない」と考えて焦って買う可能性もあるので)印象は良くない。

Vimと日本語編集(2): 修正前後の原稿の差分を一瞬でチェックする

Vimと日本語編集シリーズ第2回。
前回はこちら。
note103.hateblo.jp

けっこうニッチな内容だったと思うが、今回はもう少し使用頻度&汎用性が高いかもしれない。

前提・状況設定

複数人で利用・共有するドキュメントがあるとして、それをまず自分が書いたとしよう。

大体内容がまとまったのでデータを他のメンバーに渡し、「気になるところがあったら適当に手を入れといて」なんて言っておいたら、しばらくして修正版が届いたとしよう。

でもパッと見たところ、どこが修正されたのかわからない。

たとえば、これが修正前。*1

f:id:note103:20160907004614p:plain

そして修正後。

f:id:note103:20160907004624p:plain

そのようなときに、どうするか。

よくある解決策・その何が問題か

一番容易な選択肢としては、「じっくり見る」。
まあ、数百字程度ならありかもしれない。
とはいえ、人間に向いた作業かは微妙。避けられるなら、あまりやりたくない。

次に容易な選択肢としては、「どこ直したの?」と相手に聞く。
でも面倒くさい。すぐに返答があるとは限らないし、本人だからといって正確な差分を示せる保証もない。(だから最初の選択肢が「とりあえずじっくり見る」になってしまう)

これがエンジニア同士なら、最初からそのドキュメントはGit管理されていて、すべての差分を簡単にチェックできるようになっているかもしれない。
さらにそれがGitHubやBitbucketで共有されているなら、その視認性はさらに高まるだろう。

しかし仮に自分がエンジニアだったとしても、相手がGitを使えない人だったり、ドキュメントの性質としてGit管理の必要がないテンポラリなものだから、といった理由で差分管理が成されていなかったらどうだろう?

僕は普段の作業でGitを使っているけど、それでも既存のリポジトリには入っていない、突発的で一時的なちょっとしたドキュメントの差分を見たい、という状況にちょくちょく陥る。
そのようなとき、そのちょっとした差分を見るためだけにわざわざリポジトリを作るとか、GitHubなどにpushするというのも面倒である。

解決策

というわけで、やっているのは次のこと。

1. 白紙のバッファに差分を見たいドキュメントの「修正前」の文章をコピペ。

2. 新規で無名の分割バッファを出して、「修正後」の文章をコピペ。
この際、新規バッファを水平分割で出すなら

:new

タテ分割なら

:vnew

とすればよい。

3. おもむろに以下を打ち込む。

:windo diffthis

差分が出る。

f:id:note103:20160906231653p:plain

左が修正前。右が修正後。
変更が生じた行だけでなく、文字単位で出てくるのがよい。

差分表示を消すには以下。

:windo diffoff

上記についてはすべてVimcastsのこちらから学んだ。
Comparing buffers with vimdiff

目的の内容以外にも、その過程で次々と小ネタが繰り出されるので目が離せない。すごいコンテンツ力……。

なお、上記のexコマンドを毎回打つのは面倒なので、このようなマッピングを入れている。

nnoremap <silent> <Leader>dt :<C-u>windo diffthis<CR>
nnoremap <silent> <Leader>do :<C-u>windo diffoff<CR>

上では二つのバッファをどちらも無名ファイルにしたが、無名である必要はとくにない。
既存のファイルを二つ並べるのでも、片方だけ無名にするのでもよい。(上述のVimcastsでは片方だけ無名だった)

別解

fugitive.vim / Gdiff

もしリポジトリ管理しているファイルで同様のことをやるなら、fugitive.vimの「:Gdiff」も便利だと思う。
GitHub - tpope/vim-fugitive: fugitive.vim: a Git wrapper so awesome, it should be illegal

というか、上で紹介した方法を知るまではずっとこれでやってた。

fugitive.vimの使い方に関しては、以下の記事がとてもわかりやすい。
blog.yuku-t.com
cohama.hateblo.jp

diffsplit, VDSplit

また、今回の記事を書くためにいろいろ確認するうちにたまたま辿りついたのだけど、以下で紹介されている「:diffsplit」や「:VDSplit」でも同様のことをできるみたい。(後者はKaoriya版限定)
nanasi.jp

用途によってどれがより適している、といったこともありそうだが、そこまでは把握できていない。

まとめ

GitHubなどで色付きの、人に優しいdiffを見慣れていると、差分を知らされず変更後のドキュメントだけを渡されたときにある種の禁断症状に陥ってしまいそうな気になる。

差分を目視で確認するのも、口頭で教えてもらうのも、メールやチャットのテキストで説明を聞くのも、すべて「異様に長い箸で数メートル先の豆をつまむ」ようなもどかしさを感じる。

パパッとコマンドを打って、どの行のどの文字が変更されたのか。そして(もしかしたら変更箇所以上に)「どこが変更されていないのか」といったことがわかると、こみ上げかかったストレスが急速に収まってよい。

Vimと日本語編集: 長文の中の見出しだけを抽出する

vim

以前にすでに書いたような気がしていたが、ブログ内を検索しても出てこなかったので書いておく。
最近とくによくやる作業。

課題と前提

たとえば以下のような文書があったとする。

# 見出し1
本文
# 見出し2
本文
# 見出し3
本文
(略)
# 見出し100
本文

「本文」とあるところは何十行も続いているとして、この中から「見出し」の行だけを集めたいという場合、手動でポチポチ拾っていくのはなかなかつらいものがある。

というか、そういう手動対応はミスの介在する余地も大きいし、肉体だけでなくメンタル面でも消耗の度合いが大きいので、やらずに済めばその方がよい。

では、これをみんな大好きVimで解決するにはどうすればいいかというと、『実践Vim』の「TIP99」を使えばいい。

実践Vim 思考のスピードで編集しよう!

実践Vim 思考のスピードで編集しよう!

※同書は上記のAmazonからだと単行本またはKindleで購入できるが、達人出版会に行けばPDF+EPUBの形式でも購入できる。(たしかDRMナシ)
実践Vim【委託】 - 達人出版会
※ぼくはKoRoNさんから献本して頂いた単行本の他、なぜかKindle版も達人出版会配布のPDF+EPUB版も買ってしまった。どんだけ……。

実践: 最小限の工程

まずは、任意のレジスタをクリアする。

『実践Vim』の例ではレジスタaを使うので「qaq」と打つように言っているが、ぼくはこの用途のときは毎回何も考えずに済むよう「qqq」と打ってレジスタqを空けている。

その上で、コマンドラインモードで以下を入力。

:g /\v^# 見出し\d+/yank Q

これでレジスタqに「# 見出し(+整数)」の行が溜まっている。

次に、溜めたそれを吐き出す。
具体的には、同バッファ内で(または分割ウィンドウで別バッファを出して)以下を打鍵する。

"qp

結果。

# 見出し1
# 見出し2
# 見出し3
# 見出し100

上のサンプルを対象に実行するとこの4行が出てくるが、ほんとに100個の見出しがあれば100行になる。

工程上のポイントとしては、exコマンドの最後で小文字の「q」ではなく大文字の「Q」を入れること。
これは大文字にすることによりマッチした行がレジスタへ追記されていくからで、小文字にするとどんどん上書きされて最後にマッチしたものしか残らない。

また、レジスタqに入れているので吐き出すときは「"qp」だが、レジスタaとかbとかならそれぞれ「"ap」とか「"bp」になる。

また、この方法を使い始めた当初はよく最初のレジスタクリアをし忘れて、以前にコピーした内容も一緒に出てきてその都度けっこう驚いた。
致命的なミスではないが、毎回クリアしてから収集するのを忘れないように。

応用: 夏目漱石草枕」より

上ではけっこう厳密な正規表現を書いて対象を指定しているが、結局は正規表現で拾っているだけなので、指定をゆるくすればそれに応じた結果(対象語句を含む行)が入ってくる。

出典であるところの『実践Vim』では「TODOアイテムを収集する」というテーマになっていて、コード内でコメントアウトして書かれたTODOの行を集めるという前提で、以下のコマンドが示されている。

:g /TODO/yank A

よってたとえば、いつもお世話になっています夏目漱石先生の「草枕」より、

夏目漱石 草枕

1センテンス1行に分解した上で、「夢」を含む行だけを収集するならこんな感じになる。

:g /夢/yank Q

結果。

雨が動くのか、木が動くのか、夢が動くのか、何となく不思議な心持ちだ。
眠りながら、夢に隣りの臼の音に誘われるような心持ちである。
やがて長閑のどかな馬子唄まごうたが、春に更ふけた空山一路くうざんいちろの夢を破る。
夢に。
妙に雅俗混淆がぞくこんこうな夢を見たものだと思った。
昔し宋そうの大慧禅師だいえぜんじと云う人は、悟道の後のち、何事も意のごとくに出来ん事はないが、ただ夢の中では俗念が出て困ると、長い間これを苦にされたそうだが、なるほどもっともだ。
文芸を性命せいめいにするものは今少しうつくしい夢を見なければ幅はばが利きかない。
こんな夢では大部分画にも詩にもならんと思いながら、寝返りを打つと、いつの間にか障子しょうじに月がさして、木の枝が二三本斜ななめに影をひたしている。
夢のなかの歌が、この世へ抜け出したのか、あるいはこの世の声が遠き夢の国へ、うつつながらに紛まぎれ込んだのかと耳を峙そばだてる。
自然の色を夢の手前てまえまでぼかして、ありのままの宇宙を一段、霞かすみの国へ押し流す。
夢中に書き流した句を、朝見たらどんな具合だろうと手に取る。
しかし夢のように、三尺の幅を、すうと抜ける影を見るや否いなや、何だか口が聴きけなくなる。
この夢のような詩のような春の里に、啼なくは鳥、落つるは花、湧わくは温泉いでゆのみと思い詰つめていたのは間違である。
しかしてその青年は、夢みる事よりほかに、何らの価値を、人生に認め得ざる一画工の隣りに坐っている。
「あの山の向うを、あなたは越していらしった」と女が白い手を舷ふなばたから外へ出して、夢のような春の山を指さす。

全3212行のうち、上記15行にヒットした。

工夫: マッピングに仕込む

慣れるまではなかなか覚えられない技だが、最近はこんなマッピングを仕込んで、とくにコマンドを思い出さなくても使えるようにしている。

nnoremap <Leader>qy  :<C-u>g //yank Q

便利。

別解: tagbarを使う

これと近いニーズで、「見出し行を集めるのではなく、ただザラッと全見出しを閲覧したいだけ」とか、「任意の見出し行にジャンプしたい」という場合もあり、そういうときはtagbarというプラグインMarkdown用のプラグインと組み合わせて以下のようにしているのだけど、

f:id:note103:20160903145618p:plain

これについてはまた時間のあるときに。

まとめ

ということで、普段、日本語の長文テキストを編集しているときに多用している技(というか)をさらっと(でもないが)紹介してみた。

Vimで日本語のテキストを編集しているなどと言うと、時々「それはない」という反応があるが、このように非常に便利なのでそれを示したかったというのもある。

実際には、こういう便利さは対象を「日本語」に限定しなくても、英語でも中国語でも同様に享受できるわけだけど、とはいえプログラミングにおけるVimの便利さとは少し性質も違うだろうと思ったのであえて「Vimと日本語編集」というシリーズタイトル的なものにしてみた。

中島聡著『なぜ、あなたの仕事は終わらないのか』感想: 最大のパフォーマンスを引き出すために

book

Kindle Unlimitedで読めると知って、本書を読むためにKindle Unlimitedに登録した*1

著者は有名な方なので、名前や活動歴はざっくり知っていたが、少し前にハフポストに載った以下の記事を読んで、同書に興味を持った。

www.huffingtonpost.jp

おおよその雰囲気はその記事からもつかめると思うが、個人的に「これは新鮮だな」と思ったところをいくつか書いておきたい。

1. 脱ラストスパート志向

とりあえず、本書の一番のテーマはこれだと思う。

仕事が終わらない人は最終盤の逆転を狙ってしまう。ギリギリまで行動を起こさず、締切り&徹夜パワーで乗り切るぜ、みたいな夢を見ては失敗する。学びがない。

著者はそうじゃなくて、与えられた時間の最初の2割でまず作業全体の8割を終わらせろ、という。
もしその時点でそこまで終わらなかったら、残り8割の時間で全体を終わらせることはできないから、と。

この2割・8割の法則じたいはどうしても直感に反するというか、さすがに極端ではと思わなくもないが、それでも深く共感するのは、そういったラストスパートのパワーに幻想を持つな、みたいなことで、その点は非常に参考になると思った。

その流れで著者は朝型生活を勧めるのだけど、ぼく自身は40を過ぎて自分が今のところ非・朝型だとつくづく感じるので、そのまま生かすことはできないものの、「1日の前半にコアタイムを持ってきて後半は流せ」という思想じたいは活用できそうだと感じた。

2. 脱マルチタスク主義

本書には「なるほど〜」「ですよね〜」と感心・納得するポイントが満載なのだけど、中でも膝を打ってしてしまったのはこれで、仕事に集中したかったら作業中は一つのことだけをやれ、という。

1日を複数の時間帯に区切り、それぞれの時間内で別の作業をするのはOKだが、一つの作業中は別のことを考えるな、と。

これはぼくの感覚にも非常にフィットする考え方で、まったく同感だが、とはいえ現実の世界ではどうしても割り込みタスクや、その他集中を拡散してしまうあれこれというのはあるもので、やはり初めからこれを意識するのとしないのとでは大きな違いが出るだろう。

また、ぼくには一方でマルチタスク主義というのか、様々な異なる作業を並行して処理する良さ、みたいなことを考えてしまうときもあって、そういうブレというかゆらぎの余地を少なくする意味でも良い指針になった。

もう一つ、これに近い発想というか考え方として、「スラック(心の余裕)を持つ」ということについても触れられていて、それも大変面白く、役立つと思った。

心の余裕を持つことで作業に集中しやすくなる、と言葉で言うのは簡単だが、実行するのはそう簡単でもない。
しかしこうして、他人がバシッと言ってくれるとそれが後押しになって今まで以上に実現しやすくなりそうだと感じる。

3. 責任感とは

本書では著者がかつて勤めたマイクロソフトや、同社のトップだったビル・ゲイツに関するエピソードもいろいろと語られるのだけど、その中でもひときわ印象的だったのが、「パーティー会場に花束を届けるようビル・ゲイツから指示された人*2」の話だった。

これについては著者による以下のブログ記事でも引用されているので、興味があればそちらを読んでほしいが、

Life is beautiful: デカルトは「困難を分割せよ」と言い、ビル・ゲイツは「問題を切り分けろ」と言った

ここで問題となっている人は、指示された通りに花が会場に届くようオーダーするのだけど、花屋の都合で届かない。

そしてこのとき、その人は自分が「花を注文しろ」と指示されたのだと解釈しているから、自分の仕事はすでに完了していて、花が会場に届かないのは「花屋の責任」だと思っている。

しかしビル・ゲイツはその人に「花を届けろ」と指示したのであって、届かなければそれは指示された人間の責任なのだという話。

この、「花を注文するまで」が仕事なのか、それとも「花を届けるまで」が仕事なのかという認識のズレというのは、本当にリアルで生々しく起こりがちな状況なので「うわ〜」と思った。
本書ではいくつもそういう「うわ〜」を感じたけど、中でも「うわ〜」度が高い話だった。

しかしまあ、「え、俺はちゃんと注文しましたけど? 悪いのは花屋ですよね」と言う人にこんな話をしたところで、それが通じるとも思えない。
この話を生かせるとすれば、自分が「自分の仕事はどこまでなのか」を考えるときだろう。

4. モックを作る

自分は締切りを守って仕事をしていても、協業者の仕事が遅れたらその影響で自分の作業も遅れてしまう。そういうときにどうするか? という話。

これまた上記の花屋の話に匹敵する「あるある」話で、読みながら「いやまじで、そういう場合ってどうしたらいいの? 教えてください!」という感じで読み進んだが、書中の回答は「モックを作る」。

言い換えると、待っている間にとりあえず自分で大ざっぱな代替物を作ってしまって、それをもとにその続きにある自分の作業を進めておく、ということ。

これまた「なるほどね〜」という感じだった。

ちなみに、本書ではこれとは別に、「物事を進めたかったら書類をまとめるとかじゃなくてとりあえず目に見える成果物、プロトタイプを作れ」みたいなことが何度も言われるのだけど、ここで言うモックはそれに似ていながらけっこう本質的に違う。

プロトタイプの話も大変有用ではあるのだけど、それ以上にぼくがこのモックの話を「すごい」「こりゃ役立つな」と思うのは、結局それも花屋の責任の話と同じで、今までぼくは他人が遅れたせいで仕事が遅れたら、「俺のせいじゃないもん。あの人が遅れたせいだもんね」と、自分の責任ではないものとして済ませようとしていたと思われ、それは感じ方としては自然だが、現実的にはそうじゃない、ちゃんとやりようがあるのだ、と気付かされたという点で大きな話だった。

5. 認知資源

ふたたびビル・ゲイツの話。ビル・ゲイツは社員から何か専門的な話を聞くときに、対象の一人ひとりから直接話を聞くのではなく、それらの話を解釈してビル・ゲイツにわかりやすく説明する「専門の説明係」を雇って、その人からだけ話を聞いていたという。

そうやってつねに同じ人の解釈や説明能力といった「一定のフィルター」を通して話を聞くことで、個々の社員の多様さに左右されない、安定した低コストで情報を収集していたということ。

非常に徹底しているし、合理的だと感じる。
そのまま自分に応用することはできないとしても、何かしらの似たような工夫で、普段感じている負荷を下げることはできるかもしれない、と感じた。

なお、この際、そのように物事を考えたり判断したりするリソースを「認知資源」と呼ぶこと、たとえばそれは朝、その日に着る服を選ぶときにも消費される資源であること、といった話も紹介されており、この「認知資源を無駄遣いしない」という考え方にも非常に共感を覚えた。

5. 英語・資格の勉強法

英語や資格の勉強をやろう、というときに、明確な目的がなければ達成は困難だという話。

むしろ、そうした勉強が長続きしなかったり、集中できなかったりするのは「勉強自体が目的になってるからでしょ」ということ。

もしちゃんと目的があって、勉強があくまでその「手段・経過」でしかないなら、そもそも集中できないとかあり得ないじゃん、みたいな。

これもまたわかりやすい。なるほど、目的がない(または弱い)から勉強が長続きしないのか、と。説得力がある。

と同時に、ぼくがたとえば英語や資格、あるいはプログラミングの勉強を中途半端にしかできないのは、それをチャラチャラしたファッションというか、アクセサリーのように身にまといたいからなのだ、とこの話を読んでほとんど初めて気がついた。

そして、それならぼくは今後もチャラチャラとした、目的にもなっていないような弱い目的をもってそれらに取り組もう、とも思った。

本書の主張に基づくなら、「英語ペラペラになりたい」などという願望は英語を勉強する目的になっていない。そこには曖昧なイメージ(雰囲気)があるだけで、具体的な「英語を使ってこれをしたい」という対象がないからだ。
しかし「ファッション(=自分を飾る道具)として英語を身につけたい」と考えるなら、それは充分に「目的」と言えるし、そこにはひとまず「こんなふうになりたい」というイメージがあればよい。

そして結局のところ、ある種の取り組みの成果を左右するのは、それを「続けるかどうか」に尽きる。

これまでぼくは、ただなんとなくそれらの勉強をしていたが、なるほど飾りとしてそれを身につけたいのか、と目的を意識化できた気がするので、今後はその目的に沿ってトライを続けてみたい。

7. 好きを仕事に

終盤で語られる、ある意味で身も蓋もない話。

ひと言で言うと、「集中できないとか悩む以前に、そもそも自然に集中できない仕事なんかするな」ということ。

それが本当に好きなことだったら、「どうしたら集中できるんだろう」なんて考えるまでもなく、あるいは誰かから言われるまでもなくそれに没頭してるだろ? という。

たしかにそうだ。返す言葉もない。そして著者は重ねて言う。
「自分が本当にやりたいことを見つけろ」

この辺りの話が猛然と語られる第6章は、他のどの章とも違う独特の面白さがある。

あまりに本質的で、それゆえ抽象的で、読みながらぼんやりしてしまう部分もあるのだけど、そのままふと立ち止まって、「好きなことか……ていうか、俺って何が好きだったんだっけ?」と胸のあたりを覗き込む、その感覚はけっこう久しぶりだと感じる。

そのまますべてを真に受けて、そうだそうだ! という感じでもないのだけど、それでも時々読み返したくなる話だと思う。

本書には他にもいくつもの「なるほど〜」があって、なかなか飽きない。
実践的だったり、抽象的だったり、マイクロソフト時代のような具体的な話もあれば、いきなり「界王拳」が飛び出したりもする。

個々のトピックが印象的なせいか、全体を通しての軸というか、大きな構造というのはちょっと見えづらいのだけど*3、上でぼくが自分なりの7点をピックアップしたように、読者それぞれが自分に必要な部分、役立つ知見を再構成しながら活かしていくことはできるだろう。

ちなみに、上で触れられなかった次点的なトピックを備忘録がてら書いておくと、「昼寝の有効性」「もしも編集者がこのメソッドを使うなら」「まず調べる」「予習勉強法」といったところか。

昼寝はぼくもよくやるし、本の編集は(曲がりなりにも)自分の仕事なのでそれもびっくりした。
「調べる」ことの意義、効果の高さについてはけっこうサラッと書いてあるのだけど、ちょっとすごみを感じる重要さだと思った。

という具合にネタは尽きないが、ひとまずここまで。

*1:いろいろな評判が出ているが、個人的にはKindle Unlimitedとてもよい。サンプル(試し読み)の拡大版として考えれば充分値段に見合う内容だと思える。

*2:このエピソード自体は実話ではなく、ビル・ゲイツが嫌う「仕事や時間に遅れる人の言い訳」と、それを嫌う理由をわかりやすく説明するための喩え話だと思われる。

*3:章の構成は第1章〜3章、第4章〜5章、第6章、と大きく3部に分かれていてきちんと練られていると思うが。

『スクラム実践入門』感想: チーム開発の参考書

book

発売後けっこうすぐに買ってはいたのだけど、少し目を通してそのままにしていたのを2週間ぐらい前から少しずつ読み直して、けっこうみっちり最後まで読んでみた。

スクラム実践入門 ── 成果を生み出すアジャイルな開発プロセス (WEB+DB PRESS plus)

スクラム実践入門 ── 成果を生み出すアジャイルな開発プロセス (WEB+DB PRESS plus)

ひと言で感想を言うと、本としてよく出来ていて、道具のようにひき続き使っていけそう、という感じ。

「本としてよく出来ている」というのはどういうことかと言うと、たとえば構成がシンプルでよい。

第1章 ソフトウェア開発の困難にスクラムで立ち向かう
第2章 スクラムチーム
第3章 スクラムイベント
第4章 スクラムの作成物
第5章 スクラムを支えるプラクティス
第6章 GMOペパボの事例 ── どのように導入したか
第7章 mixiの事例 ── 導入失敗からの立てなおし
第8章 DeNAの事例 ── 大規模開発,業務委託への適用
第9章 スクラム導入時によくある問題と解決策
第10章 スクラムチームでよくある問題と解決策
第11章 スクラムイベントでよくある問題と解決策
第12章 スクラムの作成物によくある問題と解決策
http://gihyo.jp/book/2015/978-4-7741-7236-1#toc から章題のみ抜粋)

概説的な第1章を除くと、複数の章が一連のパターンを持つひとかたまりのブロックのように構成されていて、それが各章内でも同様に(入れ子のように)繰り返されていく。
たとえば上記の12章は、大きく第2章〜5章でひとかたまり。第6章〜8章が同じくひとかたまりの2周めで、第9章から12章が3周め、というふうに分けられる。

一度このパターンが体に馴染むとあとはそのリズムに乗って読んでいくだけというか、「次はこんな感じの話が来るだろう」と予測しながら読んでいけるので本質的な差分に集中しやすく、とくに後半は楽しく読めた。

「とくに後半は〜」と書いたが、それは本の後半という意味ではなく、読書体験の後半である。
というのも、ぼくの場合は第1章から順番に読んだのではなく、まず第5章、その次に2章を読んで、そこから3、4……と終盤に向けて読み進め、最後に第1章を読んだから。

なぜそんな変則的な順番で読んだのかと言うと、第1章は抽象的・俯瞰的な話であり、しかし読み手の自分としては何よりもまず具体的な話、つまりこれを導入したチームではどんなことをやるのか、それによってチーム開発を襲うどんな問題にどう対処できるのか、みたいな「結局、スクラムってなんなん?!」ということを知りたかったので、最初に我慢して抽象的な説明を読んでいるとすぐに飽きてしまいそう、という懸念があった。

それでパラパラとめくった中でもとりわけ「具体的に何をやるのか」について書いてありそうな第5章から読んだのだけど、これは半分正しく半分失敗で、何しろスクラムというのは「スプリントレトロスペクティブ」とか「プロダクトバックログ」とかいった専門的な用語を多用する方法論で、しかし第5章では「もうそういう説明は今までの章で存分にしたよね」という前提で、そういう用語の再説明などはしないので、いきなり途中から読んでもそうした用語が出てくるたびに「ぐぬぬ……意味わからん……日本語で喋れや……」みたいになってしまってつらかった。(これは読者が悪い)

と同時にしかし、これも冒頭に書いた「本としてよく出来ている」の一面なのだけど、同書は巻末の索引が非常によく出来ていて、そのような不良読者であっても、ちょっとつまづいた用語に出会うたび、索引をちょっと引いて、その初出で説明されている部分をちらっと読めば大抵「はあ、そういうことね」と、おぼろげであれ把握できる。

もちろん実際にその章や前後をみっちり読まないことには、深く理解することはできないわけだが、少しでも早く「ようするにどんなことをやるの?!」を知りたかった自分にとってはとりあえずそんな感じで充分だった。

索引を多用しながら第5章を読み終えて、さあ次はどれがいいかな、と考えたとき、先に挙げた目的からすると、

これを導入したチームではどんなことをやるのか、それによってチーム開発を襲うどんな問題にどう対処できるのか

第6章以降の導入事例に進めばよいところなのだけど、第5章の「前提にしてる用語がわからん問題」を身をもって体験した後ではあまりそういう冒険的な気持ちにもなれず、素直に最初から読み進めようということで、具体的な説明の最初となる第2章から順に読むことにした。

ちなみに、これも「本のつくり」で感心した部分なのだけど、同書では巻頭に各章の執筆分担がけっこう細かく明記されていてよかった。
共著の本だと時々、どの章を誰が書いているのか明示されていないことがあるのだけど、実際には複数人がドロドロ溶け合いながら執筆しているわけではなく、仮に編集段階で溶けているとしても中心的な担当者というのはいるはずで、ぼくの興味としては「どこの誰が責任をもってこれを書いたのか」を非常に知りたいので、どのページを読んでいても「なるほど、あの人がこういうことを考えた&書いたのか」と想像しながら読むことができてよかった。

スクラムとは何か? という、スクラムの詳しい内容については第2章から第5章までの4章でだいたい説明される。

第2章は「チーム内の役割分担」について。
第3章は「スクラムで何をやるのか」について。
第4章は「スクラムで何を作るのか」について。
そして第5章は、その過程で用いられる様々な技というか方法を具体的に紹介している。

これらをロールプレイング・ゲーム*1に言い換えると、
第2章は「キャラクターの職業」を紹介するような章なので、「戦士・魔法使い・僧侶」がいるよ、みたいな感じ。
第3章は、それらのキャラクターを使って何をやるのか。という意味では、「たたかう・まほうをかける・にげる」があるよ、みたいな感じか。
第4章は旅の目的を示すようなものなので、「レベルを上げる・コインをためる・敵を倒す」とか。
そして第5章はその道中で使用する技や道具の博覧会。魔法の種類(ギラ・ベホマパルプンテ)とか、武器や道具(薬草・鋼のつるぎ)にはこんなのがあるよ、みたいな感じ。

これらを最初の方にも書いたとおり、一定のテンプレートというか書法にそってぐるぐる反復するように説明していくので、読んでいて小気味よい。

そしてしみじみ思ったのだけど、いきなり第5章を読んだときに感じた「専門用語、多すぎだろ!」という感覚は徐々に薄れ、いやこれ、どっちかというとかなり極限までシンプル化されてるかも? みたいな感じになってくる。

たとえば第2章で紹介されるロール(各役割)なんて基本3種類だけである。
それは第3章も4章も同じで、どうもこのスクラムというのは、必要以上に選択肢を増やさないよう意識して作られているのではないかと感じられる。

原理・原則を最小限にすることによって、なるべく多様な現象に適応できるようにしている、といったところだろうか。

第6章から8章までの導入事例では、とくにDeNAのそれが面白いと感じた。

第9章から第11章までの「問題と対策」的なブロックでは第11章がとくに面白かった。あるあるの連続。

ぼくの仕事はソフトウェア開発ではなく、おもにCDブックの制作を編集者およびチームリーダー的な立場でやっているのだけど、それでも「うわー、これなあ……」みたいな「よくわかる!あるよねえ〜それ……」みたいに思えるエピソードが多く、その共感でき具合が楽しかった。

やっぱり人間同士、やっぱりコミュニケーション、難しいし面白い。だいたい似たようなところでつまづいて、それぞれそれなりの解決策なり、解決できなさなりがある。
いろんな人がいろんなことを考えていろんなものを作っているから、ひと筋縄ではいかない。そしてそういうのって、業種や場所が違ってもやっぱり似たり寄ったりなんだなあ、とじんわり実感した。

さてそのように、「具体的に何をやるのか」をざっくり把握した上でようやく第1章に戻り、ひとまず全体を読み終えて思ったのは、これだけバラエティにとんだ、かつ豊富な情報を詰め込んでいるにもかかわらず、本自体は非常にコンパクトというか、ページ数も少なくてそれがすごい、とまた本のつくりに関する感想になってしまう。

ページ数が少ない=軽いので、持ち運びもラクだし、一家に一台ならぬチームに1冊、いやチームメンバー1人につき1冊、共通の参考書として配ってもいいんじゃないかと思うほどのポータビリティ&内容の過不足のなさである。

また、ぼくのチームでスクラムを導入する予定は今のところないけれど、部分的に取り入れられる部分は少なくないと感じた。
たとえばぼくはプロジェクトの開始から完了に至るまでのタスクの洗い出しや、それぞれにかかる時間の見積りなどをけっこう細かく設定しているので、「バーンダウンチャート」なんて案外取り入れやすいかもしれない。

最後に、本書を読んでぼくが得た一番大きなものは何かと考えてみると、以前はこうした「スクラム」とか「アジャイル」みたいなものに対して、ある種の胡散臭さというか、「造語ばかり使いおって……」みたいな不信感・偏見を抱いていたのだけど、それが一気に払拭されたということではないか、と思っている。

実際にはこのスクラムでは、上記のように、そういった専門的な概念は必要最小限に絞られていて、もしそれでも残った専門用語を別の汎用的な一般名詞などに置き換えてしまったら、無用な誤解や混乱を招いてしまう可能性が出てくる。

スクラムはメンバー間のコミュニケーションを最適化するための取り組みでもあるから、使う言葉も最大限誤解の余地がないものでなければならず、その点からもある程度特殊な用語が必要とされるということについては理解できたと感じる。

一方で、ではそうしたスクラムに対するストレスというか、偏見みたいなものがなぜ発生してしまうのか? という点が新たな興味の対象にもなりつつあるのだが、これについてはまた機会をあらためて考えてみたい。

*1:単にドラクエだった。