[Jiemamy-dev:43] Re: [RFC] Collectionのアクセサメソッドについて

Back to archive index

Junichi Kato j5ik2****@gmail*****
2008年 6月 8日 (日) 22:31:08 JST


かとうです.

MIYAMOTO Daisuke さんは書きました:
> 都元でっす。
>
> ぱっと見てみたんですが、このS2のforEachメソッドは、第4案とは違う考え方なんでしょうか〜。
> 根本的な違いはあんまり感じなかったんですが。。。
>   

あそうですね.第4案のグループに入るとは思います.

for(ColumnModel column : table.getColumns()) {
// 前処理
  System.out.println(column.getName());
// 後処理
}

実際ループで処理すべきことは,ここでは 

 System.out.println(column.getName());

だけなんだけど,実際にはそうもいかず,要素を取り出したときと,要素を処理したときの後処理などが入ってくるので
できるだけ,ループの処理もオブジェクト化して,AOP的なアプローチがすぐにとれるようにしてます.
以下のような感じです.基本的には案4 (Iterable型)として,utilパッケージにTraversalがあると便利だと思いますが.

Traversal.forEachColumn(table, new Traversal.ColumnHandler(){
	public Object processColumn(Column column) {
		// Columnをお気に召すまま
		return null;
	}
});

public class Traversal {

	public static interface ColumnHandler {
		Object processColumn(Column column);
	}

	public Object forEachColumn(Table table, ColumnHandler handler) {
		for(Column column : table.getColumns()){
			// 前処理	
			Object result = handler.processColumn(column.clone());
			// 後処理
			if (result != null){
				return result;
			}
		}
		return null;
	}

}




> 2008/06/08 18:55 Junichi Kato <j5ik2****@gmail*****>:
>   
>> 加藤です。
>>
>> 断片的ですみませんが、forEach話だけに反応しますw
>>
>> http://s2container.seasar.org/2.4/s2-framework/ja/apidocs/org/seasar/framework/container/util/Traversal.html#forEachContainer(org.seasar.framework.container.S2Container,%20org.seasar.framework.container.util.Traversal.S2ContainerHandler)
>>
>> このあたりのインターフェイスを見習ったらどうかと思うのですが、
>>
>> forEachComponentメソッドなんぞはS2コンテナ内部で管理しているコンポーネン
>> トをforEachで検索するためのインターフェイスです。
>> forEachのループ部分は、インターフェイスを指定してやれば自由に定義できま
>> す。私の場合はその場で無名クラスを実装して解決してしまいます。
>> 非常に楽ちんですし、forEachで渡す要素をcloneしてから渡せば、もとのコレク
>> ションを破壊することもできませんし、またコレクションの更新が
>> 必要なら、コレクション自身を渡すのではなく、ここでいう無名クラスにそのた
>> めのコンテキストを渡してあげて更新できるようにすればよいと
>> 思います。
>>
>> 以上!
>>
>>
>> MIYAMOTO Daisuke さんは書きました:
>>     
>>> 都元です。
>>>
>>> コミットはまだしていませんが、一足先に、最低限必要なメソッドの実装を始めています。
>>>
>>> そこで迷っているのですが、Collection系のフィールドのaccessorメソッド(特にgetter)です。
>>> 例えば、TableModelにはList<ColumnModel> columnsフィールドがあります。
>>> このフィールドの直接のgetterを用意するのは、実装を公にし過ぎなんですよね。
>>>
>>> 地豆会でも指摘があった通り、TableModel#addColumn(column) では、変更を捕捉して
>>> ChangeEventを飛ばす訳ですが、万一 getColumns().add(column) されてしまった場合、
>>> 変更を検知することができません。
>>>
>>> というわけで、カラムの追加という観点では、columnsのgetterは使わず、addColumn
>>> メソッドを用意する、ということになると思います。
>>>
>>> 次に、暫くすると「テーブルが持つカラムをforで回したい」という状況が頻繁に訪れます。
>>> 従来ですと、これを実現する為に、getColumns() を用意し、
>>>
>>>
>>>       
>>>>>> 案1 (従来型)
>>>>>>
>>>>>>             
>>> ---- TableModel
>>> public List<ColumnModel> getColumns() {
>>>   return columns;
>>> }
>>> ---- client
>>> for(ColumnModel column : table.getColumns()) {
>>>   System.out.println(column.getName());
>>> }
>>> <<<
>>>
>>> というコードを書いていました。しかし、これが必要だからといってgetColumnsを用意して
>>> しまうと、先の「getColumns().add(column)」を回避することができません。
>>> bacchusでは「回避できないので、とりあえずやらないように気をつける」という
>>> 対処を行って来ましたが、なんとかしたいもんです。
>>>
>>> 現在俺の頭にあるのは「columnsのイテレータを返すメソッドを作る」という手段と、
>>> 前どこかで話が出た「forEachメソッドを作る」という手段です。
>>>
>>>
>>>       
>>>>>> 案2 (Iterator型)
>>>>>>
>>>>>>             
>>> ---- TableModel
>>> public Iterator<ColumnModel> getColumnIterator() {
>>>   return columns.iterator();
>>> }
>>> ---- client
>>> Iterator<ColumnModel> itr = deptTable.getColumnIterator();
>>> while(itr.hasNext()) {
>>>   ColumnModel column = itr.next();
>>>   System.out.println(column.getName());
>>> }
>>> <<<
>>>
>>>
>>>       
>>>>>> 案3 (ForEachHandler型)
>>>>>>
>>>>>>             
>>> ----
>>> public interface ForEachHandler<T> {
>>>   void handle(T model);
>>> }
>>> ---- TableModel
>>>       public void forEach(ForEachHandler<ColumnModel> handler) {
>>>               for (ColumnModel column : columns) {
>>>                       handler.handle(column);
>>>               }
>>>       }
>>> ---- client
>>> deptTable.forEach(new ForEachHandler<ColumnModel>() {
>>>   public void handle(ColumnModel column) {
>>>     System.out.println(column.getName());
>>>   }
>>> });
>>> <<<
>>>
>>>
>>> しかし前者に関しては「なんかイテレータって前時代的じゃね?@@:」という
>>> イメージがあったりします。もしかしたら、この意識間違ってる?(汗
>>>
>>> で、後者に関しては「キモくないですか? 大丈夫ですか?w」という危惧があります。
>>> 安全性を確保できても、見通しが悪くなってしまうのでは採用の価値低いですからねぇ。。。
>>>
>>> この辺り、意見をまとめたいと思いますので、コメント下さい。
>>>
>>> と、ここまで書いて、良いアイデアが思いついた気がします。
>>> getColumnsでList<ColumnModel>を返すからいけないんだ。
>>>
>>>
>>>       
>>>>>> 案4 (Iterable型)
>>>>>>
>>>>>>             
>>> ---- TableModel
>>> public Iterable<ColumnModel> getColumns() {
>>>   return columns;
>>> }
>>> ---- client
>>> for(ColumnModel column : table.getColumns()) {
>>>   System.out.println(column.getName());
>>> }
>>> <<<
>>>
>>> これならば、iterableにはadd出来ないので安全、かつ、見通しの良いforが書ける!
>>> なんか結論出ちゃった気がしますがw みんなが見れば案4はキモいかもしれないw
>>> ということで、一応ご意見ぼしゅー。
>>>
>>>
>>>       
>> _______________________________________________
>> Jiemamy-dev mailing list
>> Jiema****@lists*****
>> http://lists.sourceforge.jp/mailman/listinfo/jiemamy-dev
>>
>>     
>
>
>
>   




Jiemamy-dev メーリングリストの案内
Back to archive index