12月
30
2009
0

俺ルールだ!@JAVA

研究用にJavaのコーディングしてたら、疲れてきたのでブログにエントリでも書いてます。

前置きですが、自分、基本的にデザインパターン(正確には巷で使われているデザインパターンの中身)が嫌いです。
理屈っぽすぎて、理解しがたいしコードが汚くなるし・・・orz

というわけで、最近、俺ルールなデザインパターンを構築しつつありますw
あと、俺ルール支援クラスライブラリも構築していますw

イベント駆動のプログラミングをするために、デザインパターンではObserver パターンを用いることになります。
このパターン、あまり好きになれません(´・ω・`;)
なぜなら、イベント駆動中にハンドラの変更が行われることを想定した設計になると、クラス毎に複雑な設計が必要になるからです。
単純にリストにリスナ突っ込んで、for-each で回すだけなら簡単なんですけどね・・・これやるとバグの温床になるので。

正直、イベント処理は言語レベルで対応しておいて欲しいと思うのですが・・・まあ、ないものねだりをしてもしかたないので、C#の event 修飾子 を模倣した Event<T> クラスを作ってみました。

JAVA:
  1. package ncommon;
  2.  
  3. import java.util.LinkedList;
  4. import java.util.List;
  5.  
  6. /**
  7. * イベントを管理するクラス。
  8. * @author naou
  9. */
  10. public class Event<t> {
  11.     private List</t><t> handlers = new LinkedList</t><t>();
  12.     private List</t><t> copyHandlers = new LinkedList</t><t>();
  13.     private boolean changed = false;
  14.    
  15.     /**
  16.      * イベントハンドラを追加する。
  17.      * @param handler
  18.      */
  19.     public void addHandler(T handler){
  20.         handlers.add(handler);
  21.         changed = true;
  22.     }
  23.    
  24.     /**
  25.      * イベントハンドラを削除する。
  26.      * @param handler
  27.      */
  28.     public void removeHandler(T handler){
  29.         handlers.remove(handler);
  30.         changed = true;
  31.     }
  32.    
  33.     /**
  34.      * イベントコレクションを取得する。
  35.      * @return
  36.      */
  37.     public List</t><t> getHandlers(){
  38.         if( changed ){
  39.             copyHandlers = new LinkedList</t><t>(handlers);
  40.         }
  41.         return copyHandlers;
  42.     }
  43. }

handlers に対して、add/removeHander を行い、getHandlers を呼び出す際に、その複製を作るようにしています。
一見すると無駄な処理のようですが、コレは必要な処理なのです。

こうしないと、イベントハンドラ内でイベントを削除するとエラーが起きるんです^q^;
イベントハンドラリストに対して、ループ(for-each)してる祭に、イベントを追加及び削除すると、ループがおかしくなってしまうという罠です。

後は、イベントを実装したいクラスで、

JAVA:
  1. public interface IHogeHoge{
  2.     void onHogeHoge(Object sender, ...);
  3. }
  4.  
  5. Event event<IHogeHoge> = new ...
  6. public Event eventHogeHoge(){
  7.     return eventHogeHoge;
  8. }

こんな感じでイベント実装します。
ここでイベント発生元オブジェクトを sender として第一引数に指定するようにしています(C#の受け売り・・・w)

変数名は event・・・、イベント取得ゲッターは event ではじめるという、まさに俺ルールですwww

こうすれば、あとは任意の場所で、

JAVA:
  1. ...
  2. obj.eventHogeHoge().addHandler(new IHogeHoge(){
  3.     public onHogeHoge(Object sender, ...){
  4.         System.out.println("Called hogehoge");
  5.     }
  6. });
  7. ...

ってな感じで、イベントの内容を実装できます☆

あとついでに、Box<T>クラスを作ってみました。イメージとしてはポインタですね。
C# でいうところの out 修飾子代わりだったり、hoge == null ? default : hoge の代わりだったり、同期処理の支援のためだったりと、このクラス、何かと役立ちそうですw

JAVA:
  1. package ncommon;
  2.  
  3. /**
  4. *
  5. * @author naou
  6. */
  7. public class Box</t><t> {
  8.     private T object = null;
  9.  
  10.     public Box(){
  11.     }
  12.  
  13.     public Box(T object){
  14.         this.object = object;
  15.     }
  16.  
  17.     public void clear(){
  18.         set(null);
  19.     }
  20.  
  21.     public boolean isNull(){
  22.         return object == null;
  23.     }
  24.  
  25.     /**
  26.      * @return the object
  27.      */
  28.     public T get() {
  29.         return object;
  30.     }
  31.  
  32.     public T get(T defaultValue){
  33.         if( isNull() ){
  34.             return defaultValue;
  35.         }
  36.         else{
  37.             return get();
  38.         }
  39.     }
  40.  
  41.     /**
  42.      * @param object the object to set
  43.      */
  44.     public void set(T object) {
  45.         this.object = object;
  46.     }
  47.  
  48.     @Override
  49.     public boolean equals(Object obj) {
  50.         if(obj instanceof Box){
  51.             Box b = (Box)obj;
  52.  
  53.             if( object == null ){
  54.                 return b.isNull();
  55.             }
  56.             else{
  57.                 return object.equals(b.get());
  58.             }
  59.         }else{
  60.             return false;
  61.         }
  62.     }
  63.  
  64.     @Override
  65.     public int hashCode() {
  66.         int hash = 7;
  67.         hash = 89 * hash + (this.object != null ? this.object.hashCode() : 0);
  68.         return hash;
  69.     }
  70. }

あとは、変数の設定が行われるたびにイベントを発生する EventedBox( extends Box ) とか、一行ごとにReadLine/WriteLine イベントを発生する EventedReader/EventedWriter 等など・・・便利そうなクラスを色々作っています。
あとは、ロガーとかも、WriteLog イベントを実装して、任意のログ出力処理を容易に書けるようにしています。

前に日記に書いた XmlDataDocument クラスをフルスクラッチして、XData クラスも作りました。
バグもつぶして、前よりも簡潔にアノテーションを指定できるようにしました。
これで、任意のXMLとJavaクラスのマッピングができるようになりました☆
Webアプリケーションとかで、XMLでデータを受け取った時に、Javaのオブジェクトにマッピングするといった事ができるようになりました。
XDesirialized を実装することで、デシリアライズした際に、妥当性を検証することもできます。
このクラスについては、いつかまたエントリでも書きます(`・ω・´)b

Written by ナ王 in: Java | タグ: ,
10月
04
2009
0

気に入らないなら作ればいい

今回は java の話。

Java のシリアライズって、本来の目的であるオブジェクトの永続化という意味では結構使い勝手がいいです。
しかし、設定ファイルにXML用いる場合など、"人が見る” or "人が書く" 事を目的とした場合は非常に使いにくいと言わざるを得ません。
また、場合によっては、シリアライズに対応させるためにコードの可読性・安全性を下げる結果にもなります。
本来 private にしておきたい項目まで public にせざるを得ない場合もあります。

つまり、細かい不満点までまとめると・・・

  • 作られるXMLファイルの形が気にくわない
  • シリアライズ対応の為に、コードの安全性・可読性を下げたくない
  • JAXP周りが鬱陶しい…一行で読み込ませろ!

という不満点があるわけです。

はっきりいって、java は嫌いです。 エンタープライズにおいては優秀な言語であることは認めますが、あくまで趣味の範囲で使う言語としては不向きです。
しかし…開発環境の整えやすさ、ライブラリの充実度、クロスプラットフォーム、ランタイムの普及率、この辺りはかなり便利です。 嫌いでも使う意味があります。

というわけで、自分仕様の Java用 XMLシリアライザ 作ってみました。
目的は

  • 綺麗なXMLファイルを読み書きする
    (人が気持ちよく読み書きしやすいように、クラス名等はXMLに含めない)
  • シリアライズの為にコードを汚さない
    (アクセッサやアクセス修飾子を強要しない)
  • 一行で読み書きできる
    (Javaの流儀から反しますが、気にしない)

あたりを達成することにします。

とりあえず気合いで作ってみました。
実際のデータクラス定義はこの通りになりました。

JAVA:
  1. @XmlNode
  2. public class Configure {
  3.     @XmlValue private Integer count= 20;
  4.     @XmlValue("file") private String filename = "./result.txt";
  5.     private User[] users;
  6.  
  7.     public Configure(){
  8.         users = new User[3];
  9.         users[0] = new User("御手洗", "某会長");
  10.         users[1] = new User("山田", "花子さん?");
  11.         users[2] = new User("鈴木", "古都町の鈴木さん");
  12.     }
  13. }
  14.  
  15. @XmlNode
  16. public class User {
  17.     private static int tindex = 0;
  18.  
  19.     @XmlAttribute private Integer index = tindex++;
  20.     @XmlValue private String name = "";
  21.     @XmlValue private String info = "";
  22.  
  23.     private User(){
  24.     }
  25.  
  26.     public User(String name, String info){
  27.         this.name = name;
  28.         this.info = info;
  29.     }
  30. }

という感じにデータ定義クラスを書けます。
数値型や文字列型に対しては XmlAttribute / XmlValue を指定することで、出力対象になります。 XmlValue("xxx") と書くことで出力時に別名をつけれます。
クラスの定義時に XmlNode を指定すると そのクラスが XMLの出力対象になります。private な項目でもおkです。 読み込みonly な設定情報クラスであれば、メンバ変数を pulicにする必要も、セッターメソッドを用意する必要もありません。

XmlNode を指定したクラスの配列も出力対象となります。
XmlNode なクラスは無引数のコンストラクタを必要としますが、private でOKです。

本来であれば List/Set/Map も対象にしたかったのですが、クラスの型情報がコンパイル時に保持されないので断念しました。 Java ならジェネリクス型の List/Set/Map を用いたいところですが、実装が型消去による実装なので、実行時に型情報を取得できません orz

ちなみに、以下が このクラスのシリアライズ/デシリアライズ のコードになります。
・シリアライズ

JAVA:
  1. Configure config = new Configure();
  2. XmlDataDocument.save(config, new File("test.xml"));

・デシリアライズ

JAVA:
  1. Configure config = (Configure)XmlDataDocument.load(Configure.class, new File("test.xml"));

やっぱ、これくらいの単純さがいいです(´・ー・`)

ちなみに、出力されたXMLファイルは以下のようになります。

XML:
  1. <?xml version="1.0" encoding="UTF-8" standalone="no"?>
  2. <configure>
  3.   <count>20</count>
  4.   <file>./result.txt</file>
  5.   <users>
  6.     <user index="0">
  7.       <name>御手洗</name>
  8.       <info>某会長</info>
  9.     </user>
  10.     <user index="1">
  11.       <name>山田</name>
  12.       <info>花子さん?</info>
  13.     </user>
  14.     <user index="2">
  15.       <name>鈴木</name>
  16.       <info>古都町の鈴木さん</info>
  17.     </user>
  18.   </users>
  19. </configure>

こんな感じになります。
だいたい見てわかると思いますが、構造はアノテーションとリフレクトを多用して得ています。どうせならこの構造情報を元に DTDも出力できるようにしてもいいかもしれません。

とりあえず、まだ作りたての超アルファ版なので、コードはまだ出しません ←
・・・恥ずかしいからな!(^ω^;
エラーメッセージも適当だし\(^o^)/
今後は、IXMLEvent を実装したクラスでは、シリアライズ前後のイベントを拾えるようにしてみたり、IXMLNodeを実装したクラスは自由にノードを扱えるようにとかしてみようと企んでます。

あえて、コンパイル済みのバイナリとjavadoc をおいておくぜ!
もし使いたい人とかいたら、もうちょっと修正してソースも公開しちゃうぜ(`・ω・´)

xmldata
xmldata.javadoc

・・・今ふと思ったけど、同様の記述方式で O/R マッパー書いても面白いかもしれない。
あくまで、超簡易な入出力のみの・・・。
テーブル作成と、スキーマ表示、簡単な検索、データの挿入、削除、編集・・・ができればいい気がします。

こんなイメージかな・・・?

JAVA:
  1. @DBTable
  2. public class SampleTable {
  3.       @DBValue String name;
  4.       @DBValue Integer count;
  5.       @DBReference Category category;
  6. }
  7.  
  8. @DBTable
  9. public class Category {
  10.       @DBValue String name;
  11.       @DBValue String info;
  12. }

うーん、これだけ書いておいたら、

JAVA:
  1. DB db = new SQLite(new File("data.db"));
  2. // DB db = new MySQL("sample_db");
  3.  
  4. db.checkAndCreateTable(SampleTable.class);
  5. SampleTable[] ts = db.select("・・・この辺どうしよう/(^o^)\・・・");

こんな感じで使えるようにするとか!
妄想は進むけど・・・実際作ると面倒なんだろうなw

Written by ナ王 in: Java, プログラミング | タグ: , , ,
7月
26
2009
0

javaのクラスには歴史を感じる

javaのクラスライブラリは歴史を感じますね^^
不可思議な実装や名前も、歴史を考えると面白いものです。

そろそろ、過去の遺産切り捨てて新Java作ってくれないかなぁ・・・。
前も書いた気がするけど、イベントドリブンなコードを書きやすくしてほしい。

そんな今日・・・ObjectInputStream のコンストラクタに、非ブロックのソケットのInputStream与えたら・・・
java
.nio.channels.IllegalBlockingModeException が発生しました^q^

あうあうあう・・・
非ブロック非対応でした^q^
ううー設計を変えないと;;

Written by ナ王 in: Java |
12月
24
2008
0

Javaとコーディング規約

Javaに必要なのは、クラスライブラリの拡張よりも、言語仕様の整理だと思うんだ。
正直、何でもかんでも、コーディング規約で制御しようってやりかたは良くないと思う(例: getter, setter, Listener 等)。
予約語を増やさないという方針も有りかもしれないけど、多少増えるのは仕方ないと思うんだ。

やはり、プロパティ構文は必須だと思う。
get~ ってのは、オブジェクトに何らかのメッセージを送り、それに対するレスポンスとしてのオブジェクトを得るために使う”メソッド”であって・・・

今のJavaでは、get"メソッド"と、オブジェクトのプロパティを明確にかき分ける事が出来ないのが現状だったり・・・

でも、流石にJavaの開発者もこれくらい感じてるだろう・・・と思ってたら・・・
なんと、次のJava7 でプロパティ構文を採用するようです。

イヤッフー。

あとは、イベントドリブン駆動型に関するサポートが欲しいところです・・・。
GUI扱っている人くらいしか、イベントドリブンなコーディングはしないかも知れませんが・・・
やはりここも、コーディング規約で固められてるんですよね(文法上定められてないのでどうにでもかける)

今作ってるプログラムは、イベントドリブンな形で作ろうと思ってるのですが・・・Javaの標準的な規約で作ると面倒(コード量が多い)なので、独自の規約で作ることにしました。
ジェネリックを使えばかなり簡潔には書けますけど、やはり文法上定められてるC#等に比べると、冗長な書き方になってしまいます。。。

Written by ナ王 in: Java, プログラミング |
12月
19
2008
0

GA

何にでも適用できるアルゴリズムとして、GAとかSAが有名です。
何かと作っておくと便利かな、と思ったので、GAのエンジンをJavaで作ってみました。

正直、適当に作りすぎて、バグが怖いんですが・・・w
もしバグとか、あまり良くない記述などありましたら、コメントにて報告してくれたら幸いです。
ライセンスはBSDってことで、ご自由にお使い下さい。
gaengine

あと、サンプルコードって事で、ナップサック問題を解くコードを書いてみました。
knappsack

Powered by WordPress | Aeros Theme | TheBuckmaker.com