Trac 投稿専用の Windows アプリケーションを作る

前回、Trac に XML-RPC 経由でチケットを投稿する | Moonmile Solutions Blog で、コマンドライン版ができたので、これを windows アプリケーションから作ります。

通常、Unix/Linux の場合には、コマンド呼出をアプリケーションの内部に持って、パイプでつなげるという手法を取ります。windows アプリの場合でも、コマンドラインツールに GUI をくっ付ける場合は、そうします。
また、ライブラリとして切り出すことも可能なのですが…実は、.NET の場合には、直接コマンドラインツールを参照設定することで、ツール内にあるクラス(今回は、TracTools クラス)を使えます。クラスライブラリは DLL に限らず、普通の exe ファイルでも使えるのです…という例ですね。

今までは、COM で作ったり、DLL で関数を共通化したりという小細工が必要(設計段階で考えなくちゃいけなかったという意味で)になるのですが、.NET の場合は、exe を直接クラスライブラリとして扱えるので、適当なクラス分けさえしてあれば、windows アプリケーションとして動作させるのも簡単なのです。

# まぁ、コマンドラインツールのほうで、適度にクラス化が必要なわけですが。そのあたりが、UIDD(User Interface Driven Development)に繋がります。

windows アプリのコードは以下のようにさっくりと、

namespace TracWin
{
	public partial class Form1 : Form
	{
		public Form1()
		{
			InitializeComponent();
		}

		private void Form1_Load(object sender, EventArgs e)
		{
			_trac.Setting.Url = "http://localhost:8000/trac/gokui-ios5/login/rpc";
			_trac.Setting.UserName = "masuda";
			_trac.Setting.Password = "masuda";

		}

		private string _Repoter = "masuda";
		private TracTools _trac = new TracTools();
		private Ticket _ti = null;

		/// <summary>
		/// 新規作成
		/// テキストボックス等をクリアする
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void buttonNew_Click(object sender, EventArgs e)
		{
			textBoxID.Text = "";
			textBoxID.Enabled = true;
			textBoxSummary.Text = "";
			textBoxRepoter.Text = _Repoter;
			textBoxOwner.Text = "someone";
			textBoxDescription.Text = "";
			textBoxAction.Text = "";
			textBoxActionValue.Text = "";
			_ti = null;
		}

		/// <summary>
		/// 指定IDのチケットを読み込む
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void buttonGet_Click(object sender, EventArgs e)
		{
			if (textBoxID.Text == "")
				return;
			int id = int.Parse(textBoxID.Text);
			Ticket ti = _trac.TicketGet(id);

			textBoxID.Enabled = false;
			textBoxSummary.Text = ti.Summary;
			textBoxRepoter.Text = ti.Reporter;
			textBoxOwner.Text = ti.Owner;
			textBoxDescription.Text = ti.Description;
			_ti = ti;
		}
		/// <summary>
		/// チケットを書き込む
		/// IDが空白の場合は、新規登録。
		/// IDが空白でない場合は、更新登録。
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void buttonPost_Click(object sender, EventArgs e)
		{
			if (textBoxID.Text == "")
			{
				// 新規登録
				Ticket ti = new Ticket();
				ti.Summary = textBoxSummary.Text;
				ti.Description = textBoxDescription.Text;
				ti.Reporter = textBoxRepoter.Text;
				ti.Owner = textBoxOwner.Text;
				int id = _trac.TicketCreate(ti);
				textBoxID.Text = id.ToString();
				_ti = ti;
				textBoxID.Enabled = false;
			}
			else
			{
				// 更新登録
				int id = int.Parse(textBoxID.Text);

				Ticket ti = _ti;
				ti.Description = textBoxDescription.Text;
				ti.Owner = textBoxOwner.Text;
				_ti = _trac.TicketUpdate(ti);
				textBoxID.Enabled = false;
			}
		}
		/// <summary>
		/// 指定IDのチケットを削除
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void buttonDelete_Click(object sender, EventArgs e)
		{
			if (_ti == null)
				return;
			_trac.TicketDelete(_ti.ID);
			textBoxID.Text = "";
			textBoxSummary.Text = "";
			textBoxRepoter.Text = _Repoter;
			textBoxOwner.Text = "someone";
			textBoxDescription.Text = "";
			textBoxAction.Text = "";
			textBoxActionValue.Text = "";
			textBoxID.Enabled = true;
			_ti = null;
		}

		/// <summary>
		/// アクションを更新
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void buttonAction_Click(object sender, EventArgs e)
		{
			if (_ti == null)
				return;
			string act = textBoxAction.Text;
			_ti = _trac.TicketUpdate(_ti, act);
		}
	}
}

画面もチープな感じでよいので、こんな感じ。

こんな風にプロトタイプを作る場合には、

  1. コマンドラインツールで動作確認
  2. 適度にクラス分けをしておく(特に呼び出し形式に注意)
  3. チープな画面で windows アプリとして作る

という流れで作ります。NUnit が絡むところは、1 と 2 の間ぐらいなのですが、1 で動作確認をしていると NUnit を使わなくてもそこそこ動作ができます。いわゆるコードの品質が上がります。
windows アプリを作る 3 の段階では、既に内部の動作確認済みなので、GUI との結合だけを確認します。
そして、その後、画面をリッチにしたり、ボタンの制御(不要なときは押せないとか)の処理を入れていきます。

こういう風に組み立てていくと、不思議な動作による手戻り…というかバグ解析が減るので、結構効率があがりますよ、という話です。あと、今回の trac を xml-rpc でアクセスするような内部動作がいまいち不明な場合、try and error が必要な場合は、こんな風に手順よくやっていったほうが結果的に早く終わります。

カテゴリー: 開発, C#, Trac パーマリンク