| 著作一覧 |
dictionary.Add(data.key, data.foo + "," + ConvertBar(data.bar) + "," + data.baz);
...(幾つかのメソッドが間に挟まる)
try
{
string d = map[input.key];
string[] data = d.Split(',');
if (data[0] == input.Validation_key)
{
Command c = new Command("insert into ..." + data[0] + "','" + data[1] ...
...
}
}
catch (NotFoundException e)
{
throw new ArgumentException(input.key + " not found");
}
...
なぜ、ここでCSVを使うんだ? dictionaryへ元のdataを突っ込めばいいだろ?
と激しく質問。
だって、ConvertBarするし、dataは読み取り専用だからbarのセッタが無いし、……し、……し……
だったら、使う場所でコンバートしたらどうだ?
dictionary.Add(data.key, data.foo + "," + data.bar + "," + data.baz);
...
Command c = new Command("insert into ..." + data[0] + "','" + ConvertBar(data[1]) ...
これは等価だろ?
確かに……
で、これが等価だということは、
dictionary.Add(data.key, data);
...
FooData data = map[input.key];
if (data.foo == input.Validation_key)
{
Command c = new Command("insert into ..." + data.foo + "','" + ConvertBar(data.bar) ...
とも等価だよな?(書いていて思ったが、Webアプリケーションのエスケープ問題と同根だな。なぜか変形した後のデータを保存したくなるらしい――ここでのinsert……は置いておくとして)
dictionary.Add(data.key, data.foo + "," + ConvertBar(data.bar) + "," + data.baz + "," + currentStatus);
...(幾つかのメソッドが間に挟まる)
try
{
string d = map[input.key];
string[] data = d.Split(',');
if (data[0] == input.Validation_key)
{
Command c = new Command("insert into ..." + data[0] + "','" + data[1] ...
...
}
}
...
はい?
いや、ステータスが追加になったんで……
なぜクラスを作らないんだ?
はて?
CSV作ってSplitするオーバーヘッドを考えたらクラスを作ったって同じだろ? (と、インスタンス生成のオーバーヘッドを言ってるのかと思った)
……(ぽかーん)
(あ、まったく考え付かなかったということか)たとえば
internal class FooWithStatus
{
internal FooData data;
internal string status;
internal DataWithStatus(FooData d, string s)
{
data = d;
status = s;
}
}
...
dictionary.Add(data.key, new FooWithStatus(data, currentStatus));
...(幾つかのメソッドが間に挟まる)
try
{
FooWithStatus fs = map[input.key];
if (fs.data.foo == input.Validation_key)
{
Command c = new Command("insert into ..." + fs.data.foo + "','" + ConvertBar(fs.data.bar) ...
...
とするだけでも、全然ましだろ?(すでに現実とは異なる展開)
あれ、妙に洗練されてきてるな?
internal class FooWithStatus
{
FooData data;
string status;
internal DataWithStatus(FooData d, string s)
{
data = d;
status = s;
}
internal FooData Data
{
get { return data; }
}
internal string Status
{
get { return status; }
}
}
...
dictionary.Add(data.key, new FooWithStatus(data, currentStatus));
...(幾つかのメソッドが間に挟まる)
try
{
FooWithStatus fs = map[input.key];
if (fs.data.foo == input.Validation_key)
{
Command c = new Command("insert into ..." + fs.Data.foo + "','" + ConvertBar(fs.Data.bar) ...
...
せっかくのクラスだからちょっとカプセル化を意識してみました。
internal class FooWithStatus
{
FooData data;
string status;
internal DataWithStatus(FooData d, string s)
{
data = d;
status = s;
}
internal string Status
{
get { return status; }
}
internal string Foo
{
get { return data.foo; }
}
internal string Bar
{
get { return ConvertBar(data.bar); }
}
static string ConvertBar(string s)
{
...
}
}
...
dictionary.Add(data.key, new FooWithStatus(data, currentStatus));
...(幾つかのメソッドが間に挟まる)
try
{
FooWithStatus fs = map[input.key];
if (fs.Foo == input.Validation_key)
{
Command c = new Command("insert into ..." + fs.Foo + "','" + fs.Bar ...
...
はあ?
internal class Foo
{
FooData data;
string status;
internal DataWithStatus(FooData d, string s)
{
data = d;
status = s;
}
internal bool IsInsertable(string s)
{
return data.foo == s;
}
internal Command createInsertCommand()
{
return new Command("insert into ..." + data.foo + "','" + ConvertBar(data.bar) ...);
}
static string ConvertBar(string s)
{
...
}
}
...
dictionary.Add(data.key, new Foo(data, currentStatus));
...(幾つかのメソッドが間に挟まる)
try
{
Foo foo = map[input.key];
if (foo.IsInsertable(input.Validation_key))
{
Command c = foo.createInsertCommand()
...
これで、呼び出し側はFooDataなんかについてそもそも意識する必要がなくなった。入力されたキーに一致するFooが存在して、しかもインサートすべき状態ならば、インサートするためのコマンドを作ってもらって、実行する。どのオブジェクトにどの役割を与えるかを決定して分離すること。これがカプセル化ということだ。すさまくじ、おもしろい。と、ひっくりかえるくらにいおもしろい。
関数あたりは笑いを抑えるこたできないなぁ。途中、おれにはわけわかんないが、おもしろ過ぎてさらに最後で大爆笑。
こういうセンスってすげえ。
追記:あろはさんがまとめている。
追記の追記:斉藤さんのawk for Haskeller。
ジェズイットを見習え |
追記のリンクがおかしいようです。
どうもありがとうございます。直しておきました。