assertを使おう

assertって普段みんな使っているでしょうか?
私はassertを使ってプログラムを書く事はよくあります。

Wikipediaから引用

表明(ひょうめい、Assertion)とは、プログラミング言語の構文の一種であり、そのプログラムの前提条件を示すのに使われる。アサーションとも呼ばれる。表明は、プログラムのその箇所で必ず真であるべき式の形式をとる。多くの言語ではそのような前提条件のチェックに表明を使用するが、設計上の判断を文書化するのに使う場合もある。

assertを使うと何が良いか

バグの検出が早くなる

assertが失敗すると即座にプログラムが終了し、
以下のように異常終了した関数、ファイル名、行数がコンソールに出力されます。

Assertion failed: (0), function main, file test.c, line 10.

何も書かない場合だとデバッガで一つ一つ変数の値を見ていったりしないといけないので、
デバッグ時間を減らす事ができます。

プログラム設計が良くなる

表明をする事でプログラムの設計が文章化できます。
以下は配列の合計値を計算するプログラムです。

#include <stdio.h>

#define ARY_LENGTH 5

int main()
{
    int ary[ARY_LENGTH] = {1,2,3,4,5};
    int sum = calcSum(ary, ARY_LENGTH);
    printf("sum = %d", sum);
    return 0;
}

/* 配列の合計値を計算する */
int calcSum(int* ary, int length)
{
    int i;
    int sum = 0;
    for(i = 0;i < length;i++)
    {
        sum += ary[i];
    }
    return sum;
}

このプログラムではcalcSum関数でエラー処理を行っていないので、
aryにNULLを入れた場合にプログラムがクラッシュしてしまいます。
プログラムにエラー処理を入れようとした場合いろいろな実装が考えられます。

  • calcSum関数でaryがNULLの場合に-1を返す
  • calcSum関数でaryがNULLの場合に『エラー』を出力し0を返す
  • main関数でcalcSum関数のaryにNULLが入らないようにする

このうちのどの実装方法が最適かどうかはプログラムを作った人の設計思想によります。
例えば、このプログラムを書いた人がcalcSum関数にはNULLを入れないという設計思想でプログラムを書いていた場合、以下のようにassertを使ってあらかじめ設計思想を明記しておくのをお勧めします。

/* 配列の合計値を計算する */
int calcSum(int* ary, int length)
{
    int i;
    int sum = 0;
    assert(ary != NULL);

    for(i = 0;i < length;i++)
    {
        sum += ary[i];
    }
    return sum;
}

こうしておく事で他の人がプログラムをメンテナンスする際、
calcSum関数にはNULLを入れてはいけない設計思想なんだなと分かり、
上位のmain関数内にエラー処理を記述しようという事になります。
つまり、最初にプログラムを書いた人の設計思想が守られやすくなります。
又、assertが書けるという事は関数の役割が明確化されているという事でもあります。
設計が悪いプログラムは関数毎の役割が曖昧な為にエラー処理を行う階層が統一化されておらず、
様々な階層でエラー処理が行われていたりするので、不具合が発生しやすかったりします。
assertを明記する事で関数の役割や仕様が明確化され設計の良いプログラムを書く事ができます。

グラデーションボタンを作る

.NETのボタンクラスを継承してグラデーション付きボタンを作りました。
VisualStudioのコントロールだけだと普通なものしかないので、
継承させたカスタムコントロールでいろいろカスタマイズするのが好きです。

/// <summary>
/// オリジナルのボタンクラス
/// </summary>
public class MyCustomButton : System.Windows.Forms.Button
{
	/// <summary>
	/// コンストラクタ
	/// </summary>
	public MyCustomButton()
	{
		// 背景描画用ビットマップを作成
		Bitmap bmp = new Bitmap(Width, Height);
		Graphics g = Graphics.FromImage(bmp);

		using (LinearGradientBrush brush = new LinearGradientBrush(g.VisibleClipBounds, 
				Color.White, Color.Cyan,LinearGradientMode.ForwardDiagonal))
		{
			g.FillRectangle(brush, g.VisibleClipBounds);
		}

		// ビットマップを背景イメージに設定
		Image = bmp;
	}
}

C#の勉強

イベント機能

C#ではイベントという機能が言語に標準で搭載されています。
イベントというのは簡単にいうと出来事が発生した事をお知らせする仕組みです。

一般的なGUIのアプリを作る時によくあるボタンを押すとボタンクリックのイベントが発生し、
特定のメソッドが実行されるような仕組みが言語に搭載されています。
イベントは以下のような使い方をします。

class Program
{
	static void Main(string[] args)
	{
		SampleClass sample = new SampleClass();
	}
}

// イベント処理のサンプルクラス
public class SampleClass
{
	private event EventHandler<EventArgs> Notify;

	// コンストラクタ
	public SampleClass()
	{
		// イベントへのハンドラ登録
		Notify += new EventHandler<EventArgs>(WriteFooEventHandler);
		Notify += new EventHandler<EventArgs>(WriteBarEventHandler);
		Notify += new EventHandler<EventArgs>(WriteBuzzEventHandler);

		// イベント発生
		Notify(this, null);
	}

	// Fooを標準出力に出力
	private void WriteFooEventHandler(object sender, EventArgs e)
	{
		Console.WriteLine("Foo");
	}

	// Barを標準出力に出力
	private void WriteBarEventHandler(object sender, EventArgs e)
	{
		Console.WriteLine("Bar");
	}

	// Buzzを標準出力に出力
	private void WriteBuzzEventHandler(object sender, EventArgs e)
	{
		Console.WriteLine("Buzz");
	}
}

結果

Foo
Bar
Buzz

イベントにはeventというプリフィックスを付けてイベントだと言う事を明示的に表します。
イベントが発生した際に呼び出して欲しいメソッドは 「+= new イベントハンドラ名」 で登録できます。
C、C++だとコールバック関数で似たような事ができますがコールバック関数を登録する際はstaticを付けている
関数を登録する必要があるので、プログラムの中で一意にしか定義できません。
C#ではstaticではないメソッドをイベントハンドラとして登録できるので特定のクラスの特定のメソッドをイベントが発生した際に
呼び出して欲しいというのも可能です。

本を買いました

週末に本屋さんで気になった以下の2冊の本を買いました。

1冊目

インターフェイス指向設計 ―アジャイル手法によるオブジェクト指向設計の実践

インターフェイス指向設計 ―アジャイル手法によるオブジェクト指向設計の実践

C#でinterfaceという概念に出会い、どういう時に使うべきかまだ理解できていないので買いました。

2冊目

ボトルネック (新潮文庫)

ボトルネック (新潮文庫)

前に「インシテミル」を読んんだとき本当に面白くて読みやすかったので、買いました。
「このミステリーがすごい! 2010年度 作家別投票 第1位」と書かれていたので期待しています。

感想

今日も仕事頑張りました。
出来事とかをいろいろ書きたいのだが、
いかんせん平日はほとんど毎日同じ事をやっているので何も事がない。
出来事ではなく今日のニュース的なのにしようかな…。