第2回 Beanをうまく作るコツ
――Beanはsetしてexecuteしてgetして活用する――
|
Beanはそれだけでは何の役にも立たない |
最初に重要なことはBeanというのは、あくまでコンポーネントという部品にすぎないということです。部品はその部品単体で動くということはありませんし、その部品だけで業務を達成するものでもありません。必ずこの部品を活用する(この部品を呼び出す)プログラムがあって初めて部品の役割を果たすことができるといえます。
まずこの解説では、この部品を活用するプログラムのことを外部プログラムと呼ぶことにします。
|
図1 Beanは外部プログラムから共有してコールされる部品 |
|
外部プログラムとプロパティの重要な関係を知る |
ここで前回解説した内容を思い出してください。Beanには必ず業務メソッドとプロパティが存在しないといけません。業務メソッドというのは、プログラムの処理の内容を記述した部分です。またプロパティというのは、業務メソッドに記述された処理が必要とする引数や処理結果を格納する変数部分です。プロパティにはJavaの変数領域(インスタンス変数)を使います。
このプロパティの存在に着目すると、実は外部プログラムとBeanの関係に非常に面白い特徴があることが分かります。プロパティの存在と密接に関係しているのがアクセッサというものです。このアクセッサが外部プログラムとBeanのやりとりに大きな役割を担っています。
以下のリスト1は、Beanの業務メソッドに相当する個所です。ここでは、筆者がこの業務メソッドにexecuteメソッドという名前を付けています。また、以下のリスト2がアクセッサです。アクセッサを作るときの決まりとして、プロパティが1つ存在したらそれに対応するアクセッサを1組(setterとgetter)用意することになっています。
|
図2 1つのプロパティに対応してsetterとgetterの1組のアクセッサが用意される |
アクセッサは、外部プログラムがBeanにデータを渡したいときや、外部プログラムがBeanの処理した結果を見たいときに使います。前者で使うのがアクセッサのsetterメソッド、後者がgetterメソッドになります。アクセッサはプロパティそのものを表しているわけではなく、普通のメソッドです。しかしアクセッサに付けられたメソッド名を見ればBeanがどのようなプロパティを持っているか判別できます。
例えばリスト2のアクセッサを見てみると、このBeanにはDBやTABLE、KEY、RESULTSといったプロパティを持っているということが一目して分かります(アクセッサの命名の仕方は第1回「ローカルBeanとリモートBean」の解説を参照してください)。
またアクセッサとなるメソッドの中に記述される処理はどういうものかというと、Javaクラスの変数にデータをセット(格納)したりゲット(参照)したりする非常に簡単な処理が基本になります。
|
図3 アクセッサのset処理とget処理 |
Beanでは、このアクセッサを経由してプロパティにアクセスするように決められています。Javaプログラムでは、外部プログラムとBeanの関係は別々のクラスという関係であることは前回説明しましたが、もしクラスが2つに分かれていたとしても、あるクラスから別のクラスにある変数を直接アクセスすることは可能です。
|
図4 クラスからクラスへ直接変数をアクセスできる |
しかし、そうであったとしても、Beanの決まりでは外部プログラムとして作られたクラスがBeanのクラスのプロパティをアクセスするときは、アクセッサを使ってアクセスするように決められているわけです。
アクセッサはメソッドです。ですから直接クラスの中のプロパティをアクセスするより時間がかかります。またアクセスする側としては、わざわざアクセッサというメソッド記述をする分だけ面倒です。それでもなぜ、アクセッサを使うことがこれほど重要なのでしょうか?
説明に入る前に、以下のリストを見ておいてください。
リスト1 業務ロジックの部分
|
1 public void execute() {
2 String DB = getDB();
3 String TABLE = getTABLE();
4 String KEY = getKEY();
5
6 try{
7 Class.forName(
8 "COM.ibm.db2.jdbc.app.DB2Driver").newInstance();
9 Connection dbConn =
10 DriverManager.getConnection(
11 "jdbc:db2:"+DB,"userid","password");
12 Statement stmt = dbConn.createStatement();
13 ResultSet rs =
14 stmt.executeQuery(
15 "select * from "+TABLE+"
where NO like '"+KEY+"'");
16
17 Vector hitList = new Vector();
18 while (rs.next()) {
19 String 社員番号 = rs.getString("NO");
20 String 名前 = rs.getString("NAME");
21 String 姓 = rs.getString("LAST");
22 String 名 = rs.getString("FIRST");
23 String 所属部門 = rs.getString("DEPT");
24 String 部門コード = rs.getString("CODE");
25 String 社内郵便 = rs.getString("ZIP");
26 String 内線 = rs.getString("EXT");
27 hitList.addElement(
28 社員番号+名前+姓+名+所属部門+部門コード+社内郵便+内線);
29 }
30 stmt.close();
31 dbConn.close();
32
33 int hitCnt = hitList.size();
34 RESULTS = new String[hitCnt];
35 for( int i=0; i<hitCnt; i++){
36 setRESULTS(i,(String)hitList.elementAt(i));
37 }
38 }catch ( Exception e) {
39 e.printStackTrace();
40 }
41 }
|
リスト2 アクセッサの部分
|
1
public void setDB(String val) {DB = val;}
2 public String getDB() {return DB;}
3 public void setTABLE(String val) {TABLE = val;}
4 public String getTABLE() {return TABLE;}
5 public void setKEY(String val) {KEY = val;}
6 public String getKEY() {return KEY;}
7 public void setRESULTS(String[] val) {RESULTS = val;}
8 public void setRESULTS(int i, String val) {RESULTS[i] = val;}
9 public String[] getRESULTS() {return RESULTS;}
10 public String getRESULTS(int i) {return getRESULTS()[i];}
|
|
外部プログラムがBeanを活用する流れ |
ここで、外部プログラムがBeanを活用するときの標準的な処理の流れを見てみましょう。ここではアクセッサが十分活躍しています。また、ここに出てくる外部プログラムは、どんなJavaのプログラムであっても構いません。例えばサーブレットと考えても問題ありません。
|
図5 外部プログラムとBeanの処理の流れ |
1 |
まず外部プログラムは、業務処理(Bean)に渡したいデータ(引数)を準備します |
2 |
次にデータをBeanに格納します。この格納作業はBeanのアクセッサのsetterメソッドを使います |
3 |
データが格納できたらBeanの業務ロジックを呼び出します。例えば、サンプル・プログラムなら外部プログラムがリスト1のexecuteメソッドを呼び出すことになります |
4 |
Beanの業務ロジックが終了すれば、処理が再び外部プログラムに戻ってきます。ここで重要なのは、業務ロジックは処理の結果をBeanのプロパティに保存するように記述されていることです。そのため外部プログラムがBeanの処理結果を知りたいときは、アクセッサのgetterメソッドを使ってBeanの中の結果データを参照しないといけません |
5 |
結果を獲得した外部プログラムは、その内容を画面に出したりプリントしたり、あるいはデータベースに書き込んだりして、また次の処理に入ります |
|
外部プログラムで使われるBeanが1つだけということはまれなので、以上の処理を外部プログラムでは繰り返して行うことになるかもしれません。この流れの特徴は、外部プログラムが業務ロジックを呼び出す前に、必ずsetterメソッドを使って引数を渡し、その次にexecuteメソッドなどの業務メソッドを呼び出します。そして最後にgetterメソッドで結果を受け取るという構造になっていることです。
プログラミング的にいえば、業務ロジックを呼び出すときにメソッドのパラメータ(引数)としてデータを渡してしまえばよいのでは? という考えもあるかもしれません。例えば上記(2)のプロパティにデータをセットする作業は、業務ロジックを呼ぶとき、executeメソッドの引数として渡します。また(4)の結果を参照する作業は、業務ロジックが終了した時点の戻り値として受け取ればいいわけです。たくさんのプログラムを作成してきたプログラマーは、本来プログラムとはそうあるべきものだと考えるかもしれません。
|
図6 executeメソッドのオプションを使っても引数は渡すことができるが… |
|
2/5 |
|