- PR -

C# JavaのObserverインターフェースのC#への移植

1
投稿者投稿内容
ひろし
ぬし
会議室デビュー日: 2002/09/16
投稿数: 390
お住まい・勤務地: 兵庫県
投稿日時: 2008-04-24 17:13
【質問】
Observerインターフェースを含むJava言語のソースコードをC#に移植する場合の実装方法についてのアドバイスを願います。ソースコードはObserverインターフェースを用いて2つのクラス間でフィールド値を複製し相互に同期させています。
(※スレッド同期についての質問ではありません。念のため。)

実装に際しては、一応、下記の2つの異なる観点を念頭に置いています。

観点1
既存のプログラム構造の修正を最小限にすることを最優先する。
(Observe互換インターフェースをC#で実装する)

観点2
可読性、保守性を最優先する。より簡潔に記述できるならC#特有の機能も活用する。
(既存プログラムの構造にこだわらない)

【質問の背景】
 リファクタリング本にGUIとドメインデータを分離し、三階層モデルを実現する手法が記述されています。この分離を実現するためにはGUIを構成するクラスとドメインデータを格納するクラスとでフィールド値の更新について相互に同期をとる必要があります。リファクタリング本にはJava言語で例題が記述されていて、Observeインターフェースでドメインデータの更新をGUIに通知することで同期を実現しています。一方、C#にはObserverインターフェースが無いため、何らかの対策を講じる必要があります。
 C#でもWindowsアプリケーション等のテンプレートをそのまま用いると、三階層では無く二階層モデルになってしまいます。この手法を使ってWindowsFormのプロパティをドメインデータとしてドメインクラスに複製することを念頭に置いています。

【参照している書籍】
「リファクタリング・プログラミングの体質改善テクニック」
ファウラー著 ピアソンコミュニケーション より
p189 観察されるデータの複製
(あるGUIコントロールでのみ有効なドメインデータがあり、
ドメインメソッドからもアクセスする必要がある)
p370 プレゼンテーションとドメインの分離
(問題領域のロジックを含むGUIクラスがある)

よろしくお願いします。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2008-04-24 17:49
引用:

ひろしさんの書き込み (2008-04-24 17:13) より:
観点1
既存のプログラム構造の修正を最小限にすることを最優先する。
(Observe互換インターフェースをC#で実装する)


Java には標準で Observer/Ovservable という名前の型、
http://java.sun.com/j2se/1.5.0/ja/docs/ja/api/java/util/Observer.html
があったと思いますが、これは別段なにかの API を呼んでいるものではないので、これと同じものを自分で作ることは容易です。(使う・使わないや、種々の権利などの話は別にして、Java にはソースコードもすべて公開されています。)
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2008-04-24 17:53
引用:

ひろしさんの書き込み (2008-04-24 17:13) より:
観点2
可読性、保守性を最優先する。より簡潔に記述できるならC#特有の機能も活用する。
(既存プログラムの構造にこだわらない)


私は C# は詳しくなくて、Observer/Observable に相当する型が標準で備わっているかなどは知らないのですが、C# は言語仕様に標準でイベントとデリゲートがあるので、それを使えばあえて Observer/Observable のようなインターフェースやクラスを作る必要性が少ないのだろうと思います。
よこけん
大ベテラン
会議室デビュー日: 2006/01/31
投稿数: 216
投稿日時: 2008-04-24 17:55
[観点1]
Java を使った経験がほぼ無いので何か勘違いしているかもしれませんが、ここここを見る限り自前で実装できそうなものですし、(パターン適用箇所が極端に少ない場合を除いて) 自前で用意するのが一番手っ取り早いんじゃないでしょうか?

[観点2]
可読性・保守性に優れているかはわかりかねますが、C# ではイベントが使えます。
イベント (C# と Java の比較)


_________________
C#と諸々
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2008-04-24 22:37
イベントに一票。

なんか、小難しく考えているように思います。もっと、プログラミングを楽しみましょうよ!!
ひろし
ぬし
会議室デビュー日: 2002/09/16
投稿数: 390
お住まい・勤務地: 兵庫県
投稿日時: 2008-04-25 14:40
ご回答ありがとうございます。

delegateを使って記述できました。
簡単に記述できたので、わざわざクラスの状態を監視する必要性は感じていません。
GUI、ドメインデータ、ビジネスロジックを3つのクラスが完全に分離できることが確認できました。
下記のような小さなクラスをドメインクラスに継承させました。
(掲載するほどのソースでは無いですが)

public abstract class Observer
{
private UpdateGuiDelegate _updateGui;

// delegateを受け取ります。
public void AddObserver(UpdateGuiDelegate updateGui)
{
_updateGui = updateGui;
}

// GUIを更新します。
public void CallUpdateGui()
{
_updateGui();
}
}

よこけん
大ベテラン
会議室デビュー日: 2006/01/31
投稿数: 216
投稿日時: 2008-04-25 15:10
_updateGui = updateGui では追加ではなく上書きされてしまいますね。
_updateGui += updateGui とする必要があります。
あと、デリゲートが null でないか検証した方がいいです。


デリゲートを使用するのでしたら、イベントを使用した方がいいと思います。
イベントもデリゲートを使用しますが、何かが発生する・したことを通知するために使用されます。
イベントハンドラの登録・削除用メソッドが暗黙に定義されるため、自前で AddObserver といったメソッドを用意する必要もなくなります。

コード:
public event UpdateGuiEventHandler UpdateGui;



という感じで定義しますが、これは

コード:
private UpdateGuiEventHandler _updateGui;

public event UpdateGuiEventHandler UpdateGui
{
    add
    {
        this._updateGui += handler;
    }
    remove
    {
        this._updateGui -= handler;
    }
}



こんな風にも書けます。
add がハンドラの追加メソッド、remove がハンドラの削除メソッドに当たります。

# 普通は簡略して最初の方の書き方をしますが、こうやって展開したコードを見るとイベントのイメージが湧きやすいと思うので紹介しました。

_________________
C#と諸々
1

スキルアップ/キャリアアップ(JOB@IT)