2007年11月13日

オブジェクト指向におけるFizzBuzz問題

   このエントリーをはてなブックマークに追加 Clip to Evernote
元ネタ:オブジェクト指向におけるFizzBuzz問題

参考サイト:オブジェクト指向におけるFizzBuzz問題に参戦

あまりにも、当たり前すぎて面白みはないけど、
僕が最もオーソドックスな解だと思うコードを書いてみた。
不思議ことに、このようなコードが提示されていないようなので、僕がアップすることに。
いわゆるテンプレートメソッドパターンですね。

abstract class Animal {
private int times = 1;
public void SetCount(int n) {
times = n;
}
protected abstract string GetSoundText();
public void Sound() {
for (int i = 0; i < times; i++) {
Console.Write(GetSoundText());
}
Console.WriteLine();
}
}
class Dog : Animal {
protected override string GetSoundText() {
return "わん";
}
}
class Cat : Animal {
protected override string GetSoundText() {
return "にゃー";
}
}

  

Posted by gushwell at 20:48Comments(8)TrackBack(0)

2007年07月11日

必要な情報は親から貰うんじゃなくて子供から貰え

   このエントリーをはてなブックマークに追加 Clip to Evernote
このタイトルは何を言いたいのかというと、

ある処理をするのに必要な情報は、それを呼び出す親プログラムから引数などで渡してもらう、ってのが普通のやり方だと思います。

でも、発想を逆転してあげることで、とても設計がすっきるとする場合があります。
引数で渡して貰うんじゃなくて、サブクラスから情報を貰うようにするわけです。
要は、Template Method を上手く活用するってこと。

特に、受け取りたいデータが沢山ある場合は、引数で受け渡すことにすると、呼び出す側の負担が増えるし、コードも読みにくくなります。

virtualなメソッドを定義し、必要な情報をサブクラスから貰うようにすれば、呼び出す側のコードがすっきりするし、責任範囲が明確になります。


もっとも、どんな場合でも使えるっていうわけじゃないけどね。
  
Posted by gushwell at 20:56Comments(2)TrackBack(0)

2007年05月15日

データ構造とプログラムの構造をあわせることは重要。

   このエントリーをはてなブックマークに追加 Clip to Evernote

あるテキストファイルを読み込み、解析するプログラムを作成したのだが、そのときの失敗。

いわゆるインタープリタパターンを利用して、

NodeA -> NodeB -> NodeC -> NodeD -> NodeB

のように、ノードを次々と移動しながら、テキストを解析するコードを書いたわけですが、深く考えずに書いたので、テキストの終わりになるまで新たなNodeをどんどん作りだし、その Nodeにある Execute メソッドを呼ぶような実装になってしまいました。
いちおうこれで目的は達したのですが、巨大なテキストを読み込むと、どんどんメソッドの呼び出しがネストしていき、スタックを大量に使う羽目になってしまいました。

スタックオーバーを起こしているわけではないので、まあいいか、とも思ったのですが、どうも気になるので再度見直すことにしました。

問題は、データの意味的な構造を考えずに、文字列の羅列としてこのテキストファイルを処理しようとしたのが、問題でした。
意味的構造にあわせ、Node の途中で、returnするように変更。

すると、今まで、ちょっと強引に実装していた部分が解消され、そのために用意していたフィールドが不要になったり、最終的に構築する木構造も、より意味を反映できるものになりました。

データ構造にプログラムの構造をあわせることって、当たり前だけどものすごく重要だと思ったしだい。


そういえば、最近、失敗した話ばかりだな。
「窓際プログラマーの失敗だらけ」にブログ名を変えようかな...
  
Posted by gushwell at 21:51Comments(0)TrackBack(0)

2005年11月25日

C#のinterfaceの説明

   このエントリーをはてなブックマークに追加 Clip to Evernote
C#のインターフェースの説明すると、「どうもピンとこない」という反応が返ってくることがあります。
そこで、いろいろな文献などを参考に、僕なりの言葉でまとめてみました。

「インターフェースは、クラスの規格を定めたもの」と考えると理解しやすいかもしれません。工業製品には、様々な「規格」が存在し、その「規格」に合った製品を作ることで、製品同士を繋げたり、ある場所に正しく設置できたりします。
interfaceは、 プログラミング言語の文法に、この「規格」の概念を持ち込んだものなのです。


どうでしょう。
  
Posted by gushwell at 22:18Comments(2)TrackBack(0)

2005年10月17日

Seasar2.NET

   このエントリーをはてなブックマークに追加 Clip to Evernote
OSCJ.net が提供している Seasar2.NET のドキュメントを読んで見る。
Java版のSeasar2を、.NETフレームワークに移植したもののようだ。
configファイルの記述が面倒そうだけれど、その恩恵を得るには仕方ないか。
むかしは、全てをテキストエディタで書かないと気が済まなかったのに、最近は、GUIツールがないと、何も出来ない体になりつつある。

ところで、Javaとオープンソースは切っても切れない関係にあるが、.NETの場合はどうなんだろう。こういったオープンソースが広く使われるようになるのだろうか。それとも、MSが提供するフレームワークのみが標準となって行くのか。

まあ、やりたいことがすばやくできれば、どっちでも良いのだけれど...
  
Posted by gushwell at 23:17Comments(0)TrackBack(0)

2005年09月27日

インターフェースと抽象クラスの使い分けについて

   このエントリーをはてなブックマークに追加 Clip to Evernote
インターフェースと抽象クラスの使い分けについて質問されることがあります。
でも、一口に、「この場合は、インターフェースで、こういった場合は、抽象クラスを使うんだよ」とは言えないところがつらいですね。
「親子関係があって、子供の共通実装部分を定義したい時には、抽象クラスで、親子関係に縛られずに、共通の操作を決めたい時には、インターフェースだよ」、と言っても、じゃあ、自分が今抱えている問題にそれを当てはめようとしたときに、
すぐにこれだ、と思える例が出てこない。フレームワークを作成している人達は、そんなことはないのだろうけれど...

で、ググッてみたら、MSDN library のページ「抽象クラスとインターフェイスに関する推奨事項」にたどり着きました。

http://www.microsoft.com/japan/msdn/library/ja/Vbcon/html/vbconabstractclassesversusinterfaces.asp

そこには、こんな一文がありました。

小さな機能単位をデザインする場合は、インターフェイスを使用します。大きな機能単位をデザインする場合は、抽象クラスを使用します。

なるほどね、と思いました。実際に、.NET Framework はこの指針で設計されていますね。  
Posted by gushwell at 22:09Comments(2)TrackBack(0)

2005年09月12日

Dependency Injection

   このエントリーをはてなブックマークに追加 Clip to Evernote
Dependency Injectionという用語を最近よく目にするようになった(まだ、耳にすることは少ない)。ようは、OCPの原則に忠実に実践するためのテクニックだ。クラス間の依存を排除することが、その後のメンテナンスや拡張に効果があることはもう言うまでもないことだが、いざ、依存を排除しようと思うと、壁につきあたる。それは、絶対にどこかで具象クラスを生成する必要がある、ということだ。

普通は、具象クラスのインスタンスを生成するコードを直接ハードコードすることが多いが、そうせずに、Clientクラスが、どのクラスに依存するかを、Clientのコンストラクタなどの引数で渡してもらうことで、コーディング時ではなく、実行時にまで依存を遅延させよう、というテクニックだ。

でも、そこまでやる必要があるのだろうか。確かに、ソフトウェア構造的には美しいし、技術者の満足度は高まると思うけど、全てのソースから依存をなくそう、なんていう方向になったら、かえって複雑になりすぎるとおもう。
多少依存があっても、簡単に修正できれば何の問題もないはずだ。どんなときに、DIの有効度が高くなるのか、そのあたりを見極めないといけないな。

Javaなどでは、このDependency Injectionを実現する汎用のフレームワーク(DI コンテナというらしい)があるらしいが、.NETでは、あるのかな。


  
Posted by gushwell at 22:35Comments(0)TrackBack(0)

2005年03月28日

ダブルディスパッチ

   このエントリーをはてなブックマークに追加 Clip to Evernote
ダブルディスパッチのサンプルとして、じゃんけんクラスを作ってみました。

public enum JyankenResult { Win, Lose, Draw }

public abstract class JyankenHand {
public abstract JyankenResult Fight(JyankenHand oponent);
public abstract JyankenResult FromChoki(Choki oponent);
public abstract JyankenResult FromGoo(Goo oponent);
public abstract JyankenResult FromPaa(Paa oponent) ;
}

public class Goo :JyankenHand {
public override JyankenResult Fight(JyankenHand hand) {
return hand.FromGoo(this);
}

public override JyankenResult FromChoki(Choki oponent) {
return JyankenResult.Lose;
}

public override JyankenResult FromGoo(Goo oponent) {
return JyankenResult.Draw;
}

public override JyankenResult FromPaa(Paa oponent) {
return JyankenResult.Win;
}

public override string ToString() {
return "グー";
}
}

public class Choki: JyankenHand {
public override JyankenResult Fight(JyankenHand hand) {
return hand.FromChoki(this);
}

public override JyankenResult FromChoki(Choki oponent) {
return JyankenResult.Draw;
}

public override JyankenResult FromGoo(Goo oponent) {
return JyankenResult.Win;
}

public override JyankenResult FromPaa(Paa oponent) {
return JyankenResult.Lose;
}

public override string ToString() {
return "チョキ";
}
}

public class Paa : JyankenHand {
public override JyankenResult Fight(JyankenHand hand) {
return hand.FromPaa(this);
}

public override JyankenResult FromChoki(Choki oponent) {
return JyankenResult.Win;
}

public override JyankenResult FromGoo(Goo oponent) {
return JyankenResult.Win;
}

public override JyankenResult FromPaa(Paa oponent) {
return JyankenResult.Lose;
}

public override string ToString() {
return "パー";
}
}

使い方はこんな感じ。
JyankenHand h1 = new Goo();
JyankenHand h2 = new Choki();
JyankenResult r = h1.Fight(h2);

if文が無いのに比較できるって、面白いですね。  
Posted by gushwell at 21:00Comments(1)TrackBack(0)