asatoの技術的な日常日記

「成長に最大の責任をもつ者は、本人であって組織ではない。自らと組織を成長させるためには何に集中すべきかを、自らに問わなければならない」  非営利組織の経営 - ピーター・ドラッカー

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

コード進化パターン:Event Object への get method の追加

久々に、コード進化のパターンを考えるシリーズの続き。パターンカタログは ここ を参照。

今回は「Event Object への get method の追加

簡単に言えば、Listener パターン(Observer パターンの一種)が適用された構造への変化の例。特に、Event Object に対する変化の例。

進化前のコードはこんな感じ:


add_get_method_to_event_object_before.jpg


public class ComponentEvent {

private String eventInfo1;

public ComponentEvent(String eventInfo1) {
this.eventInfo1 = eventInfo1;
}

public String getEventInfo1() {
return eventInfo1;
}
}

public interface ComponentListener {
public void eventOccurred(ComponentEvent e);
}

public class MyComponentListenerA implements ComponentListener {

public void eventOccurred(ComponentEvent e) {
System.out.println("event info1: " + e.getEventInfo1() );
}
}

public class Component {

private List listeners = new ArrayList();

public void addComponentListener(ComponentListener l) {
listeners.add(l);
}

public void removeComponentListener(ComponentListener l) {
listeners.remove(l);
}

public void method() {

System.out.println("before evnet");

fireEventOccurred( new ComponentEvent("aaa") );

System.out.println("after evnet");
}

private void fireEventOccurred(ComponentEvent e) {

for(ComponentListener l : listeners) {
l.eventOccurred(e);
}
}
}






変更後はこんな感じ:



add_get_method_to_event_object_after.jpg


public class ComponentEvent {

private String eventInfo1;
private int eventInfo2;

public ComponentEvent(String eventInfo1, int eventInfo2) {
this.eventInfo1 = eventInfo1;
this.eventInfo2 = eventInfo2;
}

public String getEventInfo1() {
return eventInfo1;
}

public int getEventInfo2() {
return eventInfo2;
}

}

public interface ComponentListener { // 変更なし

public void eventOccurred(ComponentEvent e);
}
public class MyComponentListenerA implements ComponentListener { // 変更なし

public void eventOccurred(ComponentEvent e) {
System.out.println("event info1: " + e.getEventInfo1() );
}
}

public class MyComponentListenerB implements ComponentListener { // 新規追加

public void eventOccurred(ComponentEvent e) {
System.out.println("event info2: " + e.getEventInfo2() );
}
}


public class Component {

private List listeners = new ArrayList();

public void addComponentListener(ComponentListener l) {
listeners.add(l);
}

public void method() {

System.out.println("before evnet");

fireEventOccurred( new ComponentEvent("aaa", 111) );

System.out.println("after evnet");
}

private void fireEventOccurred(ComponentEvent e) {

for(ComponentListener l : listeners) {
l.eventOccurred(e);
}
}
}




考察


考察としては、以下がある。

-(1)進化のリクエスタ:この例の場合、進化のリクエスタには、MyComponentListenerB が対応する。進化のリクエスタとは、ある構成要素(クラス)に、進化を要求する役割を持ったクラス。たとえば、MyComponentListenerB は、eventInfo2 の情報が必要だったので、ComponentEvent の進化、つまり getEventInfo のメソッドの追加を要求した。

まだ全ての場合を検証していないけれど、コードの進化には、進化のリクエスタみたいな関係があると思う。

一つ、この関係を考えるのが重要なのは、クラスのインタフェースは、誰かからの要求によって進化していくということ。これは、どういう意味か。進化した部分は、進化のリクエスタにとって必要だったから、ということ。別の言い方をすれば、進化した部分は、他のクラスにとっては関係がない進化だったということ。
evolution_requester.png


すべてのコード進化には、このような進化リクエスタ/プロバイダの関係を伴うのかというと、そうでもない。
evolution_requester2.png


分類すると以下が考えられる:
-進化リクエスタ/プロバイダ関係による進化:コード(サービス)は、リクエスタからの要求に答えられるように進化する。

-プロバイダによる進化:リクエスタからの要求がなくても、プロバイダはサービスを提供するように進化する。言い換えれば、あらかじめ進化リクエスタからの要求を予測した進化。

-インタラクションの進化:サービスの呼び出し(あるいは依存)関係が進化する。

-サービスの進化:サービスの仕様が進化する。

-その他の進化:それら以外の進化。


-(2)進化パターン関係:ある進化のパターンがその他の進化のパターンを伴っている場合がある。たとえば「Event Object への get method の追加」パターンは「ConcreteListenerの追加」パターンに伴って起こることがある。上記のコード例で言えば、MyComponentListenerB が追加されたことにより、ComponentEvent に getEventInfo2 の get method を追加する必要が出てきた。

evo_pattern_use.png


まとめ


「Event Object への get method の追加」という進化パターンを紹介した。このパターンから進化パターンの種類を考察した。また、進化パターン間の関係を考察した。
スポンサーサイト

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバックURLはこちら
http://asatohan.blog77.fc2.com/tb.php/55-5f70a423
この記事にトラックバックする(FC2ブログユーザー)

FC2Ad

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。