ブログトップ 記事一覧 ログイン 無料ブログ開設

Strategic Choice

2014-07-25

[]美しさ

どういうこと?

優れたソースコードには、「見た目の美しさ」が必要です。

どうして?

見た目が美しいコードのほうが、使いやすいのは明らかです。

考えてみれば、プログラミングの時間のほとんどは「コードを読む時間」です。さっと流し読みができれば、誰にとっても使いやすいコードだと言えます。

例えば、(極端ですが)以下のようなコードを使わなければならないとします。

class StatsKeeper {
public:
//doubleを記録するクラス
	void Add(double d); // と素早く統計を出すメソッド
private: int count;			/* それまでの         個数
*/ public:
	double Average();
private: double minimum;
list<double>
	past_items
		;double maximum;
};

これを理解するには時間がかかります。しかし、以下のキレイなバージョンなら、マシンには同じコードでも、ヒトには結果は異なります。

//doubleを記録するクラスと
//すばやく統計を出すメソッド
class StatsKeeper {
	public:
		void Add(double d);
		double Average();

	private:
		list<double> past_items;
		int count; //それまでの個数

		double minimum;
		double maximum;
};

どうすれば?

優れたソースコードは「目に優しい」ものでなければなりません。そのためには、コードを読みやすくするための「余白」「配置」「順序」に気を配る必要があります。

以下、目に優しいコードのための3大原則です。

  1. 読み手が慣れているパターンと一貫性のあるレイアウトを使う。
  2. 似ているコードは似ているように見せる。
  3. 関連するコードをまとめてブロックにする。

2014-07-24

[]ドッグフーディング

dogfooding

または

Eating your own dog food

どういうこと?

開発した製品(やサービス)を、自らが使用することです。

どうして?

ユーザの視点で見ることにより、「本来の改善点」に気づくことが出来ます。

ユーザが使うように使うと、開発内のテストでは見つからなかった不具合が見つかります。これを修正し、製品の安定性を向上させることが出来ます。

ユーザが使うように使うと、全く使わない機能や、逆に欲しい機能が見つかります。また、使い勝手があまり良くない機能に気づきます。これらの機能過不足を調整し、製品の魅力を向上させることが出来ます。

どうすれば?

できれば、リリース前に、自らが本当のユーザになって使用します。疑似ユーザではなく、本当に使ってみるのが望ましいやり方です。

リリース前の製品は品質が悪いので、コストのリスクはありますが、ユーザに見放されるリスクに比べたら問題になりません。

最終的に、安定性を確保してユーザにあきれられるリスクを回避し、機能を改善してユーザを魅了するリターンがあるので、やらない手はありません。

また、リリース後であっても、自らの製品は使い続けるべきです。ユーザに対して「便利です」といって製品を提供している以上、自らがそれを使用して証明する責任があるからです。

参考


2014-07-23

[]名前:誤解されない名前:複数の名前を検討する

どういうこと?

名前を決めるときには、複数の候補を検討します。

どうして?

名前は、たいていの場合、完璧なものが一発で見つかることはありません。いくつか候補を上げ、それぞれ長所(ないし短所)について話し合い、そのうえで決定するべきです。

どうすれば?

名前を決めるときには、複数の候補を検討します。

以下で、具体的な検討の例を示します。

高トラフイックのウェブサイトでは、ウェブサイトの変更によってビジネスがどのくらい改善できるかを調べる「実験」をすることが多いです。

これは、実験用の設定ファイルです。

experiment_id: 100
description: "フォントサイズを14ptに上げる"
traffic_fraction: 5%
....

設定ファイルには、属性と値のペアが15個ほど定義されています。同じような実験をするときには、設定ファイルの大部分をコピペしなくてはいけません。

experiment_id: 101
description: "フォントサイズを13ptに上げる"
//[以下 experiment_id: 100のときと同じ]
....

既存の設定ファイルを、他の実験でも使えるようにしたいところです*1。そうすれば、以下のように書けます。

experiment_id: 101
the_other_experiment_id_I_want_to_reuse: 100
//[以下変更が必要な情報だけ書き換える]
....

ここで考えなければいけないのは、「the_other_experiment_id_I_want_to_reuse(再利用したい実験のID)」の名前を何にするか?です。

以下の4つの名前を検討してみます。

  1. template
  2. reuse
  3. copy
  4. inherit

どの名前も適切に思えます。おそらく、新しい機能を追加したのが自分自身だからです。でも、この機能を知らない人が見たらどうなるかを想像しなければなりません。

そこで、それぞれの名前を検討していきます。他の誰かが誤解する可能性を考えてみます。

template
experiment_id: 101
template: 100
....

「template」にはいくつかの問題があります。

まず、「これはテンプレートだ」なのか「このテンプレートを使っている」なのか、わかりにくい点です。

次に、「テンプレート」という言葉は、抽象的なものに何かを「埋め込んで」、具体的なものにするために使うものです。テンプレートに使う実験のことを「本物」の実験ではない抽象的なものと誤解する人がいるかもしれません。

この状況で「template」を使うのは、意味があいまいすぎるようです。

reuse
experiment_id: 101
reuse: 100
....

「reuse」は悪くない言葉です。

しかし、文字だけを見ると「この実験は100回再利用できる」と誤解される可能性もあります。名前を「reuse_id」に変えたほうがいいかもしれません。ただ、それでも、「reuse_id:100」のことを「この実験の再利用idは100だ」と誤解するユーザがいるかもしれません。

copy
experiment_id: 101
copy: 100
....

「copy」はいい名前です。

しかし、「copy:100」だけでは、「この実験を100回コピーする」なのか「これは100回めのコピーである」なのか、わかりません。

「他の実験を参照している言葉」ということを明確にするには、「copy_experiment」という名前に変えるといいかもしれません。今までのところ、これが最善の名前です。

inherit
experiment_id: 101
inherit: 100
....

「inherit」という言葉はプログラマにはなじみがあります。

何かを継承するというのは、新たに変更を加えるという意味です。クラスを継承すれば、そのクラスのメソッドとメンバがすべて手に入り、それらを変更したり新しく追加したりできます。現実の世界で考えてみても、身内の財産を継承するというのは、その財産を自分で好きなように保有したり売却したりできるという意味です。

ただし、他の実験から継承していることは明確にしておいた方がよさそうです。名前は「inherit_from」や「inherit_from_experiment_id」に変更したほうがよいかもしれません。

結論

以上の検討結果から、最善の名前は「copy_experiment」と「inherit_from_experiment_id」ということになりました。これらは、何が起きるかを明確に表していて、誤解を生む可能性が低いからです。

*1:これは「プロトタイプ継承」パターンと呼ばれる手法です

2014-07-22

[]名前:誤解されない名前:ユーザの期待に合わせる

どういうこと?

誤解のない名前を使用します。

名前を見たユーザが「期待する通り」の実装を心がけます。

どうして?

名前がそれほど実装とかけ離れていなくても、その名前にユーザが先入観を持っている場合、誤解を招いてしまうことがあります。

例えば、getで始まるメソッドについて、多くのプログラマは、メンバの値を返すだけの「軽量アクセサ」であるという規約に慣れ親しんでいます。この規約を守らなければ、誤解を招く可能性があります。

以下は、その具体例です。

public class StatisticsCollector {
	public void addSample(double x) {
		//...
	}
	public double getMean() {
		//すべてのサンプルをイテレートして、「total/num_samples(=平均値)」を返す。
	}
	// ....
}

getMean()はサンプリングしたデータをすべてイテレートして、その場で平均値を計算する実装になっています。データが大量にあった場合、ものすごいコストになります。そのことを知らないプログラマは、コストが高いとは思わずにgetMean()を呼び出してしまいます。

どうすれば?

名前を見たユーザの期待通りの実装を心がけます。期待通りの実装にならないのであれば、名前の方を変更します。

上述例であれば、「getMean()」をコストの高くない実装に変えるか、コストの高さが事前にわかるように「computeMean()」という名前に変えるべきです。

2014-07-18

[]名前:誤解されない名前:true/falseの意味を明確にする

どういうこと?

誤解のない名前を使用します。

ブール値の変数やブール値を返す関数の名前を選ぶときには、trueとfalseの意味を明確にします。

どうして?

ブールは、書き方によっては誤読されやすい値です。

以下は誤解を受けやすい例です。

boolean read_password = true;

「read」には、2つの解釈が考えられてしまいます。

  • パスワードをこれから読み取る必要がある。
  • パスワードをすでに読み取っている。

どうすれば?

ブール値の「true」「false」の意味が、明確になる名前をつけます。

上述の例であれば、代わりに、「need_password」や「user_is_authenticated」を使うと意味が明快になります。

また、ブール値の変数名は、頭に「is」「has」「can」「should」などをつけるとわかりやすくなります*1。例えば、「SpaceLeft()」という名前は数値を返すように聞こえます。ブール値を返したいのであれば、「HasSpaceLeft()」という名前にします。

また、名前を否定形にするのは避けるようにします。例えば、「bool disable_ssl = false;」ではなく、肯定形「bool use_ssl = true;」にしたほうが、声に出して読みやすいし、短くて済みます。

*1:これは、言語によって慣習が異なります。RubyやSchemeでは、名前の後ろに「?」を付ける習慣があります。Lispでは、名前の後ろに「p」を付ける習慣があります。