Planning Lanugage 事始め

CakePHP の発想から、EXDoc, DBUnit のひな型を作ってきたのですが、そうか、UIDD に則ればガントチャートのような UI は冗長なのですね。もっと MVC 的に Logic 部分(Controller部分) を分離させても良いわけです。

ガントチャート – Wikipedia
http://ja.wikipedia.org/wiki/%E3%82%AC%E3%83%B3%E3%83%88%E3%83%81%E3%83%A3%E3%83%BC%E3%83%88

ブレークダウンした WBS からスケジュールに落とす時は、ガントチャートを使うことが多いのですが、本来は PERT を考慮しないと駄目です…と言いますか、最近のガントチャートツールは、このあたりを押さえている(と思う)ので問題ははないんのですが、MS Project をはじめとして、この手のツールは、

  • 高価すぎる
  • チャートを作るのが非常に手間
  • 変化に弱すぎる

のが問題です。高価すぎるところは、Excel でスケジューラーを作ったり、フリーのものを活用したりすれば良いのですが、2番目と3番目が致命的です。

WBS でもストリーカードでも良いのですが、それぞれを「タスク」あるいは「ワーク」という単位に落とし込んだ後、それをどの順番で行うのか、を組み立てるのに非常に手間が掛かります。実は、この手間は、

  • タスクの連結を、タスクを出した後に行ってしまう。
  • タスクの連結を知っているのは、開発者のみだったりする。

という理由から来ています。タスク同士の連結は、PERT 図を書いている方は分かると思いますが、前のタスクがあり後ろのタスクがあるという「前提条件」が必ずあります。これは工場で使われるプロダクトの「製造工程」と同じことで、前の製品/部品ができていなければ、後ろの工程が進みません。そのあたりをタスクを動かしても、単純に待ちが発生してしまうだけです。

で、タスクに落とすのは誰がやるかというと、マネージャがやることが多いのです。なおで、ブレークダウンしたタスクをさて、タスクの連結にするときに止まってしまいます。あるいは、シーケンシャルに並べることによって全体の工数を算出します。
この工数の算出の仕方は、「やや悪い」程度で決して「悪く」はないのですが、「良い」わけでもありません。
前後のタスクにより制約が発生しているのであれば、その制約を取り除くことで効率化をするという「制約理論」の手法を導入することで、これを「良い」方向に動かすことができます。

CCPM やクリティカルチェーン、工場の製造工程の場合には、このタスクの連結を実施者自らが考えます。と言いますか、工程のラインをどのように組み合わせるのかという専門家がデザインをします(勿論、マネージャが、工程の専門家になるのがベストなのですが、マネージャの役割として「マネジメントとしての管理者」と「プロジェクトの計画者」と「実施時の監督官」という 3 重の責務を負わせるのは難しいと思われます)。

いわゆる、「建築家」と「現場監督」の違いがある、と覚えておけばよいでしょう。

なので、現場を知る人がこのタスクの連結を知っていますという矛盾が発生しています。アジャイル開発(XP やスクラムなど)は、この責務を意図的に混沌とさせることで回避する方法です。

と、前置きが長くなりすぎましたが…ええと、話を最初に戻すと、ガントチャートを作るのに何も豊富な GUI は必要ないのです。

  • タスク自身、タスク間のデータを保持する。
  • タスク間の連結が変更しやすい。
  • スケジューリングを自動化する。
  • 最後に GUI で確認する。

というポイントを抑えておけば、ガントチャートが作成できます。と言いますか、最初の2点を抑えておけば、ガントチャートを作ることは可能なんですね。

C# や VB では、言語的な制約が多いので、いずれ F# に直す予定ですが、ひとまず UIDD 的にコマンドラインで書いてみる。


// タスクを設定
PlanA.Tasks.Add( new Task("001","最初のタスク", 2 days ));
PlanA.Tasks.Add( new Task("002","次のタスク", 3 days ));
PlanA.Tasks.Add( new Task("003","並列タスク", 2 days ));
PlanA.Tasks.Add( new Task("004","最後のタスク", 3 days ));

// 連携
PlanA.Tasks["001"].Adter = PlanA.Tasks["002"];
PlanA.Tasks["001"].Adter = PlanA.Tasks["003"];
PlanA.Tasks["002"].Adter = PlanA.Tasks["004"];
PlanA.Tasks["003"].Adter = PlanA.Tasks["004"];

// マイルストーンを設定
PlanA.Task["001"].MileStone = #2011-04-01# ;

// XML 形式で出力
PlanA.XML ;

// GUI で出力
PlanA.GUI ;

// 同じタスクで Plan B を作成する
PlanB.Tasks = PlanA.Tasks ;

// 連携を変更
PlanB.Tasks["001"].Adter = PlanB.Tasks["002"];
PlanB.Tasks["002"].Adter = PlanB.Tasks["003"];
PlanB.Tasks["003"].Adter = PlanB.Tasks["004"];

// クリティカルチェーンを取得
PlanB.CriticalChain ;

// クリティカルチェーンタスクを取得
PlanB.CriticalChain.Tasks

これは静的コンパイルをしないといけないので、F# のインタプリターを使うか、PowerShell を使います。
ま、これの実装は後ほど。

カテゴリー: 設計, UIDD, プロジェクト管理 | Planning Lanugage 事始め はコメントを受け付けていません

DBUnit の .NET 版を作成する(準備)

実は java 版の DBUnit は xml からデータを読みに行くし、DBUnit.net は動作的に同じなので、自前の DBUnit を作ります。
名前がダブっているけど、これは後から。

UIDD に則って、最初はテストケースをざっくりと作ります。
こんな風に使えると、マニュアルなしでも使えるかもね、という雰囲気で。

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using NUnit.Framework;
using DBUnit.Framework;

namespace Test.DBUnit
{
	[TestFixture]
	public class TestDBUnit
	{
        /// <summary>
        /// 前処理
        /// </summary>
		[SetUp]
		public void SetUp()
		{
            // コネクションを保持
			DB.Connection = new SqlConnection("");
		}

        /// <summary>
        /// 後処理
        /// </summary>
        [TearDown]
        public void TearDown()
        {
            // テーブルの内容を削除
            DB.Clear();
        }

        /// <summary>
        /// DataTable を使ってテスト
        /// </summary>
		[TestCase]
		public void TestSetUp()
		{
			DataTable dt = new DataTable();

			dt.TableName = "XProduct";
			dt.Columns.Add( new DataColumn("ID", typeof(int) ));
			dt.Columns.Add( new DataColumn("Name", typeof(string) ));
			DataRow dr = dt.NewRow();
			dr["ID"] = 10;
			dr["Name"] = "masuda";
            dt.Rows.Add(dr);

            dr = dt.NewRow();
            dr["ID"] = 20;
            dr["Name"] = "tomoaki";
            dt.Rows.Add(dr);

			// 前処理
			DB.Insert(dt);

            DataTable result = new DataTable();
            SqlDataAdapter da = new SqlDataAdapter(
                "SELECT * FROM XProduct", DB.Connection);
            da.Fill(result);

            Assert.AreEqual(2, result.Rows.Count);
            Assert.AreEqual(10, result.Rows[0]["ID"]);
            Assert.AreEqual("masuda", result.Rows[0]["Name"]);

            // 後処理
			DB.Truncate(dt);
		}

        /// <summary>
        /// 独自のDBUnit.DBTable を使ってテスト
        /// </summary>
		[TestCase]
		public void TestSetup2()
		{
			DBTable dt = new DBTable("XProduct");

            // デフォルト値を設定
			dt.SetDefault(
                "ID", 0, 
                "Name", "", 
                "Update_at", DateTime.Now);
            // 設定する列名
			dt.AddColumns("ID","Name");
            // 行を設定
			dt.AddRow(10, "masuda");
			dt.AddRow(20, "tomoaki");
            // insert を実行
			dt.Insert();

            // データをクリア
			dt.Clear();
			Assert.AreEqual( 0, dt.Rows.Count );

            // データベースから読み込み
			dt.Select();
			Assert.AreEqual(2, dt.Rows.Count);
			Assert.AreEqual(10, dt[0]["ID"]);
			Assert.AreEqual("masuda", dt[0]["Name"]);

            // テーブルの内容を削除
			dt.Delete();
		}
	}
}

微妙にコードが冗長なのは、.NET v2.0 を対象にしているからです。手元のプロジェクトが v2.0 なのでそれに合わせて作らないと意味がないので、というのが第一の理由。LINQ to SQL とタプルなんかを使えるともう少しマシなコードになると思うのですが、そこは v2.0 がターゲットということで。

TestSetUp のほうでは、既存の DataTable/DataRow を使ってみたパターンです。カラムを作るところがやや面倒なのですが、これだとデフォルト値を入れるのが大変なので、テストケースを作るのが苦労しそうです。

なので、TestSetup2 のように、べたべたな仕様にするのがいいかなと。
所詮 NUnit との組み合わせでテストケースにしか使わないので、分かりやすいほうが良いでしょう。型付の DataTable を作成することも考えたのですが、これは環境依存(というかプロジェクトの方針依存)になりそうなので、DataTable 風に扱います。

これをざっくりとクラスとメソッドを作って、コンパイルが通るようにしたのが下記です。

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;


namespace DBUnit.Framework
{
	public class DB
	{
        public static SqlConnection Connection;
		public static void Insert(DataTable dt)
		{
		}
		public static void Delete(DataTable dt)
		{
		}
		public static void Truncate(DataTable dt)
		{
		}
        public static void Clear()
        {
        }
	}

	public class DBRow
	{
		public int Count;
		public object this[string key]
		{
			get
			{
				return null;
			}
		}
	}
	public class DBTable
	{
		public string TableName;
		public List<DBRow> Rows;

        public DBTable(string name)
        {
            this.TableName = name;
        }

		public void SetDefault(params object[] ps)
		{
		}
		public void AddColumns(params string[] columns)
		{
		}
		public void AddRow(params object[] rows)
		{
		}
		public void Insert()
		{
		}
		public void Clear()
		{
		}
		public void Select()
		{
		}
		public void Delete()
		{
		}
		public DBRow this[ int index ] 
		{
			get
			{
				return this.Rows[index];
			}
		}
	}
}

そして、DBUnit を NUnit を使って作成する、という不思議/当たり前なことをやっていきます。

カテゴリー: C#, xUnit | DBUnit の .NET 版を作成する(準備) はコメントを受け付けていません

xUnit を使うと、どこまで効率的になるのか?

xUnit を導入する積極的な理由をメモ書き。

Windows アプリケーションでは NUnit を使える構造設計を
http://www.moonmile.net/blog/archives/2054

導入できるかどうかは上記のポイントがありますが、さて、xUnit を導入する積極的な理由はどこにあるのでしょうか?
…と言いますか、いままで何とか仕事をこなしてきたから、同じ方法でやりたいのは当然なんですよね。むやみに Change !!! もできないわけで、そこには実装者なり経営者なりのメリットが必要なわけです。

win-win な関係って奴ですね。相手に対する営業的トークも少し混じりますがw

■現場でのメリット

昔、Eclipse が無かったころは、Java のコーディングをするときには、vi/emacs で十分だよ、という意見が大半でした。Visual Basic 2.0 の頃は、統合開発環境というよりは、その言語に【密着した】コーディング環境というイメージが強いのです。
でも、今 Eclipse を使わずに Java のコーディングをすることは皆無…とまでは言いませんが、少ないですよね。PHP のコーディングでも、JavaScript のコーディングでも、それなりの IDE(統合開発環境)を使うのが普通になっています。
で、xUnit を使うというのは、それくらい【便利】なのです。

これは、以前、携帯電話の中身(アプリケーションじゃなくて、内部実装を C言語で)を作っていた頃なのですが、その頃 xUnit の導入は「導入コストがかかる」という意見が大半です。まぁ、この「導入コスト」については、

・xUnit を学習するための暇がプロジェクトで取れない。
・xUnit を作っても、単体テスト用の Excel シートを書くと二重に手間がかかる。
・現在、単体テストがうまくいっているから、xUnit を導入するメリットはない。

のように、学習コストが大きいことや、導入したときのメリット(現場レベルのメリット)がないことを理由に避けられます。

このパターンは、なにも xUnit の導入に限ったことではなく、

・VB6.0 のアプリを VB 2010 に移行する
・データベースの扱い方を、SQL 文を学習せずに、古い O/R マッピングを使い続ける。
・統合開発環境を導入しない

というような【新しいこと】に対する拒否反応…と言いますか、現状の慣性の法則が働くので、特に珍しいことではありません。心理的な障壁が多いのです。
いわゆる、新しいものが好きな開発者は、どんどん導入するのですが(かといって、新しいものを導入しすぎてあらぬ方向に行きかねませんが)、いわゆる大半の開発者はそのままなのです。

なので、

・新しいものを導入する前の、心理的な不安
・新しいものを導入した後の、メリット

を比較して、心理的な不安 < メリット となるようにします。
「心理的な」という言葉を使っているのは、過去の業務コストやら時間やらを計算してたたき出しても、「心理的な不安」は減らないからです。このあたりは、心理学を少しかじるとわかります。

さて、心理的な不安を低くする方策としては、

・学習コストが、【思ったよりも】低いことを強調する。
 → 数時間の xUnit の学習だけで済む。
 → 基本は、Assert.AreEquals だけ。
 → テストの基本パターンをあらかじめ用意する。
・単体テストの Excel 試験仕様書の記述が軽くなることを強調する。
 → 二度手間はやらない。
 → ざっと分類書くだけにする。
 → 単体テスト自体は、コードや、それに書かれたコメントで十分

を強調します。

・現在の単体テストがうまくいっているから

の理由のほうは、放置しておきます。

# そういう場合は、放置しておいたほうが「うまくいく」し、
# 逆にうまくいかない場合は、「関わらない」ほうが無難です。
# やむを得ず、関わらなければいけない場合は、トップダウンで適用します。

導入後のメリットのほうは、

・再帰試験がやりやすくなる。
 → 実際に xUnit のコードを実プロジェクト用に書いて、動かすとよいでしょう。
・複雑なロジックの完成が非常に早くなる。
 → いままで1日かかっていたコーディングが1時間で終わることも稀ではありません。
 → 慣れてくると適当なテストコードを書いても、それなりにロジックが作れるのです。

を強調し、実践します。実際に動かしてみないとメリットは分かりづらいですからね。

MVC パターンを適用していれば、他人が書いたコードに対して、xUnit を導入することもできます。
このあたり、もっと慣れてくれば、詳細設計書自体を半減させることも可能です。

■経営サイドのメリット

技術的なことは分からないけど、お金のこと(コストのこと)が気になるマネージャや経営者への説明は、技術者への説明とは違って「コストが下がる」「儲かる」ことを強調します。
まぁ、それが「経営」ってものですから。

・xUnit を導入すると、次回のプロジェクトで、単体試験のコストが半減します。
・xUnit を導入すると、プログラマを 2 割減らしても大丈夫です。
・xUnit を導入すると、詳細設計から結合設計までの期間を 2 割減らしても大丈夫です。
・xUnit を導入すると、顧客からの要求を取り入れやすくなります。
・xUnit を導入すると、不具合が半減して、品質が非常によくなります。

多少「売り」文句が入っていますが、真面目に導入するとこのくらいの削減ができます。
実は、削減≒プログラマの削減になるので、開発者にとっては痛し痒しなわけですが、他社にとっての競争力になることは確かです。「品質」がよく、「早期納入」が可能になります。

# CCPM と合わせると、「納期遅延」にも対応が可能です。

xUnit は Visual Stuido などの製品とは違って、購入コストは 0 ですから(大抵は無償で配布されています)、スタートアップでコスト的に躓くことはありません。

XP や TDD を導入すれば更に加速がつきますが、最初は xUnit の導入だけで十分です。xUnit を導入するときの【文化】として適切でない場合もあるので、そのときは従来の開発スタイルに戻すのも良いです。
適合不適合は、どこにもあるもので、それぞれの文化にあわなければ導入を見合わせたほうがよいでしょう。

カテゴリー: 仕事, xUnit | xUnit を使うと、どこまで効率的になるのか? はコメントを受け付けていません

計画停電でもできるIT屋さんのお仕事法

どうやら、計画停電(輪番停電)が4月末まで続きそうな勢いなので、IT 屋さんとしてはえーッ!!! 一日3時間も停電していたら仕事にならないよッ!!!な状態にならないように、準備をしておきます、の巻。

節電に関しては、使っていないディスプレイ消す、ノートブックで仕事をする、サーバーを落とす、など直接的な方法がありますが、私のほうは設計/実装段階で使える節電ノウハウをお伝えします。

手っ取り早く云えば、XP の40時間勤務を実践するノウハウなんですけどね。

■ペーパープロトタイピングを応用

本式なところは↓な訳ですが、

Amazon.co.jp: ペーパープロトタイピング 最適なユーザインタフェースを効率よくデザインする: Carolyn Snyder, 黒須 正明: 本
http://www.amazon.co.jp/dp/4274065669
今でも役立つ、ペーパープロトタイピングのススメ – Feel Like A Fallinstar
http://www.fallinstar.org/ui/post_104.html

もうちょっと節電できるように範囲を広げます。
例えば、UML 設計とか、データベース設計をしているときにディスプレイと睨めっこをしているのを止めます。一旦、パソコンの電源を落として、紙にプロトタイピングをします。

これ、単なる節電の効果だけじゃなくて、ディスプレイを付けているとメールやらツイッターやらインターネットやらが気になってしまって、他のことをやってしまうので、集中するという点で実に重要です。余計な情報を入れない、気を散らさないという形で紙に書いて、後からオーサリングツールに清書します。

当然、仕様書なんかが電子化されているときはパソコンを見ながらということになってしまうのですが、一部分だけ印刷をしたりしてしのぎます。iPad などのタブレットタイプやノートブックを利用しても効果があがります。要は、メールなどの余計な情報を入れない、見れない状態にすると良いという話です。

■PSP(パーソナル・ソフトウェア・プロセス)を活用する

PSP と言ってもプレイステーションのアレではなくて、パーソナル・ソフトウェア・プロセスの略です。

Amazon.co.jp: パーソナルソフトウェアプロセス入門: ワッツ ハンフリー, Watts S. Humphrey, PSPネットワーク: 本
http://www.amazon.co.jp/dp/4320120132
パーソナルソフトウェアプロセス(PSP)実践講座 ~第1日 自分の生産性・品質を算出する(1/5):CodeZine
http://codezine.jp/article/detail/3937

厳しい開発プロセスですが、時間制限があるときに非常に有効です。簡単なやり方としては、

  1. 最初に予想時間を立てる(1時間程度で)
  2. 実行して、実測値を計測する。
  3. 実測値に合わせて、予想時間を見直す。

という細かい単位で計画を見直します。いわゆる PDCA を短時間(1時間単位)で廻すという感じですね。

仕事/作業に対して集中力を要するので、だらだらした仕事振りができなくなります。ある意味で、非常に疲れるので短期間しかできないし、1日8時間弱が限界です。
ですが、集中して仕事ができるので、効率がよくなります。

停電する前に集中して作業をこなさなければならないときには、この方法は非常に有効です。

■付箋/ストーリーカードを活用する

パソコンで Excel などを使って ToDo 管理をしている場合は、一時的に付箋に書きつけるとよいです。というか、この手の使い捨ての ToDo なんかは付箋やストーリーカードに書きつけるのが、次々と仕事をこなす時に便利です。

付箋やストーリーカードについては、予定時間や完了予定日を書き込んでおきます。そして、仕事が終わったら外して捨ててしまいます。
この捨てるという行為が、結構すがすがしく、次々と仕事をしている雰囲気を生み出してくれます。

付箋に関しては、半日以内でできる仕事を書き込みます。
このリアルな感覚は、ディスプレイから離れて仕事をするときに非常に良いです。

■CCPM/GTD を活用する

CCPM(クリティカル・チェーン・プロジェクト・マネージメント)や GTD(Getting Things Done)を利用します。

Getting Things Done – Wikipedia
http://ja.wikipedia.org/wiki/Getting_Things_Done
誠 Biz.ID:Getting Things Done(GTD)まとめ
http://bizmakoto.jp/bizid/gtd_index.html

GTD に関しては、オンラインツールが多くあるのですが、最初は紙のノートに書き出したほうがよいです。思いつく限り、ボールペンで書き出すと、キーボードで打ち込むのとは違った感覚で書き出せます。

CCPM も GTD も、優先順位を付けて、優先度の高いもの、期限が近いものからやっていくというのが同じ方法です。優先度が高いものをこなすと、優先度が低いものはやらなくても良いという状態になることがあります。それが、CCPM, GTD の狙いです。

CCPM のタスク抽出や連携は、パソコン上でやるよりも大きな紙の上に付箋を貼りながらやったほうが見通しが良くなります。なので、これはオフラインの仕事に向いています。

■技術書を読もう

この際ですから、節電関係で余った時間を技術書を読むことに使っては如何でしょうか?地震の情報はインターネットで最新情報を収集することができるように
なりましたが、情報におぼれているだけで、何もできなくなっては仕方がありません。。。と言いますか、情報が過多になると人間の頭は働かなくなってしまいます。コンピュータ用語で云えば、スレッドが多くなりすぎて、本来のタスクに使う CPU が食いつぶされてしまうという状態ですね。なので、地震情報を得るのは、別途ラジオなり、定期的にテレビなりで確認するようにして、本来の自分の仕事に専念することができる状態を作ります。

阪神大震災の時には、私は大阪にいて午前4時にパソコンを弄っていました。六畳一間の下宿で、2 つの本棚が倒れたのですが、幸い寝ていなかったため(苦笑)本棚の下敷きになることは避けられました。

その後のテレビには、ちょっとばかし怒りを覚えたわけですが、本棚の本を片付けて本の整理をしてズレた机を直して(30センチ以上ずれていました)、1日経った後に日常的に大学に行きました。
停電、断水を経験したのですが、できるだけ早く日常の感覚を取り戻すことが第一です。
その上で、ボランティアなり募金なり物資支援なりをしてくださると良いかと思います。

~~

と、いちソフトウェア開発者としてできることはここまでです。
津波後の処理、東京の列車の復旧、福島原発(私は原子力学科卒なので、一般の人よりは詳細がわかります)など、問題はたくさんありますが、非難/批判よりもまずは、一歩ずつ進むことを大切にしては如何でしょうか?

カテゴリー: 開発, 設計, プロジェクト管理, 仕事, 雑談 | 計画停電でもできるIT屋さんのお仕事法 はコメントを受け付けていません

windows で objective-c を動かす

GNUstepでobjective-cを学ぶ(1) | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/595

のところで環境構築をするわけですが、

GNUstep Windows Installer
http://www.gnustep.org/experience/Windows.html

からダウンロードするのは、

  • GNUstep MSYS System
  • GNUstep Core
  • GNUstep Devel

の3つです。

最初の2つは、GNUStep を動かすために必要で、最後のGNUStep Develに gcc が入っています。

そんな訳で、objective-c の xUnit は何処だ?

OCUnit
http://www.sente.ch/software/ocunit/

Mac OS X 版しかないから、ソースからコンパイル?何故か、windows からダウンロードすると途中で駄目になるので mac からやらないと駄目か?

カテゴリー: 開発, 雑談, Objective-C | windows で objective-c を動かす はコメントを受け付けていません

コードで学ぶASP.NET MVC の目次

自分で忘れる…ってのと、目次のリンク先が自動リンクなので、直リンクにした目次を

連載! コードで学ぶ ASP.NET MVC アプリケーション開発入門 | Code Recipe | MSDN

しかし、この MSDN コード サンプル ギャラリー のところに、「ASP.NET MVC」のキーテクノロジはないんですよね。でも連載記事のほうには ASP.NET MVC というキーがあるので、不具合なのかなぁと思ったり、思わなかったり。

# あとでフィードバックを送っておこうッ!!!

カテゴリー: ASP.NET | コードで学ぶASP.NET MVC の目次 はコメントを受け付けていません

PHPでEXDocを作ってみる(準備)

C# で大方 EXDoc が動いたので、本命(?)の PHP で動かしてみるテスト。
いや、単純に

PHP: マジックメソッド – Manual
http://www.php.net/manual/ja/language.oop5.magic.php

を使えば、XML のタグ名や属性を直接書けるのでは?という思いつきです。

まずは、UIDD に従って、こんな風にコードが書けたらいいなぁ、というコードを作ります。

$doc = new EXDoc();
$els = $doc->members->person;
$els = $doc->members->person("name")->eq("masuda");
$doc->members->person("name")->value = "masuda";

何をやっているか分かりますよね。PHP の場合は / 演算子などの多重定義ができないので、普通にメソッド/プロパティ呼出しをします。
この、-> 演算子のところで、直接 members やら person やらを書くわけですが、これがメソッド名だったりプロパティ名だった利する訳です。

で、当然、このメソッドは定義していないのでエラーになります。が、PHP のマニュアルに書いてあるマジックメソッドを使うと、未定義のプロパティやメソッド名のエラーを拾うことができるのです。

これに対処したのが次の例。

<?php
class EXDoc
{
	function __call($name,$args) {
		print "func $name(";
		foreach( $args as $a ) {
			print "$a ";
		}
		print ")\n";
		return new EXDoc();
	}
	function __get($name) {
		print "get $name\n";
		return new EXDoc();
	}
	function __set($name,$value) {
		print "set $name $value\n";
		return new EXDoc();
	}
}

C# よりも更に簡単になります。未定義の関数やプロパティは、 __call __get, __set メソッドで取れるので、ここで、さらりと EXDoc を new して返してやります。すると、先のコードがするするととおって、次の実行結果が得られます。

D:\work\blog\src\php>php ex001.php
get members
get person
get members
func person(name )
func eq(masuda )
get members
func person(name )
set value masuda

見事にエラーも出さずに、目的が(半分だけ)達成ッ!!!
# 確か、Ruby には動的にプロパティを作る方法があるのですが、PHP のように未定義のメソッドを拾うことができたかどうかは不明です。

あとは、内部的に SimleXML か DOM を使って操作すればOKってことで。

カテゴリー: 開発, UIDD, EXDoc | 2件のコメント

tweetbackup もどきを作ってみる

ツイッターの全発言を取得する perl スクリプトを以前書いたので、

指定したTwitterアカウントの全ツイートを取得(perl版)
http://www.moonmile.net/blog/archives/860

今回は、C# を使ってもう少し分かりやすく書き直します。ひとまず、抜粋だけアップして、後でツールをアップということで。

    public class TwiBack
    {
        protected string _user;
        /// <summary>
        /// アカウント
        /// </summary>
        public string User
        {
            get { return _user; }
            set { _user = value; }
        }

        protected const string HTTPTWI = "http://twitter.com";

        /// <summary>
        /// ツイート数
        /// </summary>
        /// <returns></returns>
        public int GetTweetCount()
        {
            string url = string.Format("{0}/{1}", HTTPTWI, _user);

            WebClient web = new WebClient();
            StreamReader sr = new StreamReader( web.OpenRead(url));

            // <span id="update_count" class="stat_count">2,153</span>
            Regex rx = new Regex(">([0-9,]+)<");
            while (sr.EndOfStream == false)
            {
                string line = sr.ReadLine();
                if (line.IndexOf("<span id=\"update_count\"") >= 0)
                {
                    Match mt = rx.Match(line);
                    int count = int.Parse(mt.Groups[1].Value.Replace(",", ""));
                    return count;
                }
                // Console.WriteLine(line);
            }
            return 0;
        }

        /// <summary>
        /// ページ番号でツイートを取得
        /// </summary>
        /// <param name="page"></param>
        /// <returns></returns>
        public string GetTweetPage(int page)
        {
            string url = string.Format("{0}/{1}?page={2}", HTTPTWI, _user, page);

            WebClient web = new WebClient();
            StreamReader sr = new StreamReader(web.OpenRead(url));

            // <li class="hentry u-moonmile status" id="status_41673902056935425"
            List<string> lines = new List<string>();
            while (sr.EndOfStream == false)
            {
                string line = sr.ReadLine();
                if (line.IndexOf("<li class=\"hentry") >= 0)
                {
                    lines.Add(line + "\n");
                    while (sr.EndOfStream == false)
                    {
                        line = sr.ReadLine();
                        lines.Add( line + "\n" );
                        if ( line.IndexOf("</li>") >= 0 ) {
                            break;
                        }
                    }
                }
            }
            string ss = "";
            foreach ( string s in lines ) {
                ss += s ;
            }
            return ss ;
        }

        /// <summary>
        /// ツイートXMLをコンバート
        /// </summary>
        /// <param name="xml"></param>
        /// <returns></returns>
        public string ConvXml(string xml)
        {
            EXDoc.EXDocument doc = new EXDocument();
            doc.LoadXML(xml);

            EXDocument dout = new EXDocument();
            // ルート要素を作る
            dout += "tweets";
            // 変換元をループ
            foreach (EXElement twi in doc * "li" )
            {
                // 変換元から取り出す
                string id = twi["id"].Replace("status_", "");
                string content = ((EXElement)(twi * "span" % "class" == "entry-content")).Xml;
                string date = twi * "span" % "class" == "published timestamp";

                Console.WriteLine(id);
                // 要素を作る
                EXElement tweet = dout.Root.Append("tweet");
                tweet.Append("id").Value = id;
                tweet.Append("content").Value = content;
                tweet.Append("date").Value  = date;
            }
            return dout.Xml;
        }
    }

TwiBack クラスの中で、GetTweetCount メソッドと GetTweetPage メソッドはノーマルに Twitter の Web ページから発言数と発言を取得しているところです。perl 版と同様に、ブラウザ経由で取得するので、アクセス数制限はありません。ただ、返信とかしているのは取れないので、いまいちですけどね。このあたりは、OAuth でログインした後にブラウザ経由で取るように修正してきます。

# 当初の目的が人様の発言を全部取ってくるので、バックアップとはちょっとニュアンスが違うのです。

で、取得した HTML タグは、以下の形式で取得できます。

<li class="hentry u-moonmile status latest-status" id="status_42686164938932224">
	<span class="status-body">
		<span class="status-content">
        	<span class="entry-content">【メモ】 クローラのせいで重くなった MT4i の対策 - Movable Type運営記
<a href="http://bit.ly/es5CWf" class="tweet-url web" rel="nofollow" target="_blank">http://bit.ly/es5CWf</a> -- 以前から気になっていたけど、yeti は韓国系のクローラーなのか。これもブロック。</span>
        </span>
    	<span class="meta entry-meta" data='{}'>
  			<a class="entry-date" rel="bookmark" href="http://twitter.com/moonmile/status/42686164938932224">
    		<span class="published timestamp" data="{time:'Tue Mar 01 20:42:29 +0000 2011'}">12:42 PM Mar 1st</span>
    		</a>
  		<span><a href="http://moonmile.net/" rel="nofollow">TwiNetBot</a>から</span>
  		</span>
        <ul class="meta-data clearfix"></ul>
  	</span>
</li>

このままだと使いづらいので、分かりやすいように整形します。ってところで普通ならば LINQ to XML を使うのでしょうが、ええッそうですッ!!! 自前の EXDoc を使います。

/// <summary>
/// ツイートXMLをコンバート
/// </summary>
/// <param name="xml"></param>
/// <returns></returns>
public string ConvXml(string xml)
{
    EXDoc.EXDocument doc = new EXDocument();
    doc.LoadXML(xml);

    EXDocument dout = new EXDocument();
    // ルート要素を作る
    dout += "tweets";
    // 変換元をループ
    foreach (EXElement twi in doc * "li" )
    {
        // 変換元から取り出す
        string id = twi["id"].Replace("status_", "");
        string content = ((EXElement)(twi * "span" % "class" == "entry-content")).Xml;
        string date = twi * "span" % "class" == "published timestamp";

        Console.WriteLine(id);
        // 要素を作る
        EXElement tweet = dout.Root.Append("tweet");
        tweet.Append("id").Value = id;
        tweet.Append("content").Value = content;
        tweet.Append("date").Value  = date;
    }
    return dout.Xml;
}

なんか不思議な記号がいっぱいになってきてしまいましたがw、変換元から、

・id
・content(発言)
・date(発言した日時)

を拾ってきて、

<tweet>
	<id>...</id>
	<content>...</content>
	<date>...</date>
</tweet>

な形に整形します。

要素を追加するのに、いろいろ多重定義する演算子を探してみたのですが、結局のところ、Append メソッドに落ち着きました。デリゲートの追加演算子のように += 演算子を使おうとしたのですが(実装はしています)、+= 演算子を使った後に、追加した要素が取れないことになるので、やめました。

C++ だと、

EXElement *tweet = dout.Root += "tweet";
(tweet += "id") = id;
(tweet += "content") = content;
(tweet += "date") = date;

な感じで作れるんですけどね…C# だと左辺に式を置けないので、これができないのです。
あと、cout などで定番の << 演算子も C# ではなぜか数値しか使えないので、【使えない】演算子になっています。このあたりの制限が、C# はかなり変です。

とは言え、メソッドチェーンと配列を使いながら、イメージしやすい形でコーディングができます。特に、XML を作成するときは、Append を続けて子を作っていくというのがイメージしやすいと思います。これが普通の XML の構築だと、CreateNode した後に、AppendChild するので、なんか作成と挿入が遠い感じになってしまいます(まあ、作成した途端に追加すればいいだけなんですけどね)。

カテゴリー: C# | tweetbackup もどきを作ってみる はコメントを受け付けていません

RIA とは違う UIDD を模索中(準備)

RIA(Rich Internet Application)とか、UX(User eXperience)とは違った形で、UIDD(User Interfece Driven Developement)を考えようと思って、ネタ的にドメインを取ってみました。

http://uidd.net

ええ、com のほうは、$1000 ぐらいで売っているものですからw それなりに需要はあるのか、ないのか。

EXDoc を作りながら、久し振りにロジック関係に NUnit を使っていた訳ですが、やっぱりこの手のライブラリを作る手順としては、

  1. 利用者がどうつかうのか、を具体化する。
  2. その機能を実現する。

という UI 先行型のほうが良いです。この考え方自体は、RIA とか UX 以前に、ペーパープロトタイピングだとか、ペルソナ指向開発なんかがあって、アジャイル開発と相まって使われるのですが、なんだかんだと私は良く使います。
これが、普通の開発だと、

  1. 要件定義をする。要求を取り込む。
  2. 設計をする

という形で、設計のほうが後に来るもので、要件やら要求やらの曖昧なものが形になって、いざ利用するための設計(デザイン)をする段階で、最初の要求(requirement)とのミスマッチングが起こります。この「デザイン」という言葉はかなり語弊を含んでしまうのですが、2つの意味があります。

  • 見た目をデザインする。
  • 機能、利用法をデザインする。

という意味です。工業デザインの場合は、両方を考えないといけないので(例えば、いくら美しくても穴のあいたコップや、テーブルに置いただけのコップでは利用価値はないですよね)普段から行われていることなのですが、コンピュータ関係のデザインというと、この機能/利用法が欠け落ちてしまっていることが多々あります。

いわゆる UX にしても「利用価値/利用のしやすさ」の追求よりも「見ための美しさ」を追及するところが多いのです。営業的にそれがプッシュされるのも分からないでもないのですが、ずーっと、いまいちな感じがしていました。

RIA についても同じで、何故か Internet を含んでいるので、インターネットを使ったブラウザ上のという制限が付きまといます。いや、Internet だからブラウザである必要はないのですが、どうもその手の話が多い。ブラウザで使おうが、Windows アプリで使おうが、iPad のアプリで使おうが、それは利用者の選ぶところであって、提供側の選ぶところではありませんよね。なので、この制限も変な話かなぁと思っていました(

ええ、勿論営業的にプッシュするは悪くないし、そういうことは大いにやるべきことかと。

という訳で、ネタ的にではありますが、uidd.net というドメインで、もっとシビアな形で UI を実践していこうかなぁと考えました。シビアにというと、どのくらいシビアなのか、という例をだしてみると、

  • LINQ やメソッドチェーンの文法は、C# や Java の文法から外れないように作られているだけで、本来やりたいこととは別の路線に乗ってしまっているような気がする。なので、文法の制限を外してでも、本来やりたいこと(プログラマがコーディングをするという意味で)の文法を定義するべきではないだろうか?

ってなことで、

  • C# にはやっぱり、マクロが必要だよね、とか。
  • C# の左辺に変数しか入れられないのは変だよね、とか(C++は入れられる)
  • C# は拡張メソッドを入れたため、ぐだぐだになったよね、とか。
  • Java のインターフェース一杯は、変だよね、とか。
  • try-catch って、文法的に変だよね、とか

そんな話とか、HTML5 絡みで、やっぱり SVG は復活させるべきだろう、ってな感じで、

  • Flash を作るように SVG がつくれないと絶対普及しないよね、とか。
  • SVG を扱う javascript ってプログラマ寄りだから、デザイナは使わないよね、とか。
  • SVG を扱うときも、MVC で分離させようね、とか。
  • MVC で、View をテンプレート化させると、デザイナが使わないから普及しないよね、とか。

な話です。

まあ、これを IT以外の利用者に拡大していくわけで、例えば、

  • 車のハンドルは、右左ボタンじゃあ危なくってしょうがないよね、とか。
  • 車の動態認識は、ブレーキとハンドルさばきが一体化しないと意味ないでしょ、とか。
  • 実現してほしいのは iPhone とかのスマートフォンじゃなくて、クレジットカードタイプのタッチパネルでしょ、とか。
  • タッチパネルも、1枚じゃななくて、複数枚用意してしかるべきでしょ、とか(ボタン毎に液晶パネルを付けてもOKだし)。

まぁ、そんな実現と非実現のあたりをそれなりにという話。

カテゴリー: 設計, UIDD, 雑談 | RIA とは違う UIDD を模索中(準備) はコメントを受け付けていません

もう LINQ to XML はいらない(虚実編)

今度は、比較演算子をオーバーライドします。

まず、どんなことがやりたいかというと、

<members>
    <person name='masuda'>masuda tomoaki</person>
    <person name='yamada'>yamada taro</person>
</members>

こんな風な XML があったときに、name 属性が “yamada” の要素をとりたいとします。

この場合のコードを

EXElement el = doc / "members" / "person" % "name" == "yamada";

と書きたい訳ですね。LINQ の文法で言えば、where 句があって、ってことになるのですが、そんな面倒なことを EXDoc ではやりませんッ!!! と言いますか、このあたりがコード上のシンタックスシュガーな訳なのです。

% 演算子を使って属性の値が取れるので、これを == 演算子で比較します。
普通は、bool 値で true/false で返すのですが、それでは意味がないのですね。どうせならば、マッチする要素を取って来てほしい。

なので、== 演算子の戻り値を、bool 型じゃなくて、EXElements 型にしてしまいますw
なんか、後で破綻しそうな気もしますが、別に構いません。C# の文法に則ったまま、ちょっと不思議な言語を作っている気分なので。

そんな訳で、== 演算子を多重定義します。

public static EXElements operator ==(EXAttrs ats, string val)
{
    EXElements items = new EXElements();
    foreach (EXAttr at in ats)
    {
        if (at.Value == val)
        {
            items.Add(at._exElement);
        }
    }
    return items;
}
public static EXElements operator !=(EXAttrs ats, string val)
{
    EXElements items = new EXElements();
    foreach (EXAttr at in ats)
    {
        if (at.Value != val)
        {
            items.Add(at._exElement);
        }
    }
    return items;
}
public override bool Equals(object obj)
{
    return base.Equals(obj);
}
public override int GetHashCode()
{
    return base.GetHashCode();
}

どうやら、== 演算子を多重定義すると自動的に、

・!= 演算子
・Equals メソッド
・GetHashCode メソッド

もオーバーライドする必要があるので、適当に入れておきます。

こうすることで、

EXElement el = doc / "members" / "person" % "name" == "yamada";

このコードが、思った通りに動くようになります。

そう、これって UIDD(User Interface Driven Development)と言ってもいいかもとか、思いました。あるいは、You & I Driven Development とか。

一応 wikipedia にもあるみたい。ちょっと違いますが。
http://ja.wikipedia.org/wiki/UIDD

カテゴリー: 開発, C# | もう LINQ to XML はいらない(虚実編) はコメントを受け付けていません