ひがやすを技術ブログ

電通国際情報サービスのプログラマ

ダイコン時代の設計手法 - ユースケース分析

ユースケースの管理単位は、画面系なら関連のある複数の画面の組み合わせ、
帳票系なら1帳票、バッチ系ならジョブネット。
ユースケース単位に、ロバストネス分析を行って全体構造を把握します。
ロバストネス分析を行うときにもっと重要なのがコントロール
コントロールはVO(〜を〜する)で記述します。
画面系の場合は、ほぼリンクやボタンのクリックのイベントが
1つのコントロールになります。
バウンダリでは画面の入出力項目、帳票の出力項目を定義します。
ユースケースでは具体的な画面は意識しない方がいいなんてことが
いわれたりしますが、それはきれいごと。
実際はこの段階でモックを作ったほうがユーザから多くのフィードバックを
引き出すことができ、仕様をつめることができます。
業務ロジックを含まない画面の仕様はここで固めます。
エンティティはER分析のインプットです。
コントロールはステートレス。
状態がある場合は、一時的な状態はバウンダリに、永続的な状態は
エンティティにマッピングします。
この辺は、UI層のモデルの話が絡んできます。
UI層のモデルは画面項目定義に反映され、エンティティはエンティティ定義に
反映されます。
エンティティ定義は、S2DaoではExcelで定義されデータベースとの
ラウンドトリップも実現する予定です。
コントロールはこの後、UI層のコントローラ、サービス層、永続化層に
マッピングします。
UI層のコントローラの仕様は、画面のイベント定義に反映されます。
サービス層の仕様は、サービス定義書に反映されます。
ユースケース記述(ルール記述)を使ってもいいのかもしれません。

ルール記述書は、事前条件・事後条件・シナリオで構成されているもので、
詳しくはまた後で。
永続化層の仕様はSQL定義書に反映されます。
SQL定義書は、S2Daoの定義そのものであってもいいかもしれません。

S2Dao入門(1)

S2Daoではエンティティのクラスを作成するために2つの方法が提供されます。

  • Excelにテーブル定義を書いて、DDL, エンティティのソースを書き出す。DDLを直接データベースに適用することも可能。
  • 作成済みのテーブルのメタデータよりExcel、エンティティのソースを書き出す。

Excelとデータベースのラウンドトリップ開発も可能です。
これらの機能は、antのTaskとして提供されます。
今回は次のようなソースが書き出されたとします。


public class Emp {
public static final int dept_RELNO = 0;
private Integer empno;
private String ename;
private String job;
private Integer deptno;
private Dept dept;

getter, setterメソッド省略
}

public class Dept {
private Integer deptno;
private String dname;

getter, setterメソッド省略
}

Emp用のDaoを作成します。っていってもinterfaceです。

interface EmpDao {
Class BEAN = Emp.class;
List getAllEmps();

String getEmpByEmpno_ARGS = "empno";
Emp getEmpByEmpno(Integer empno);

String getEmpsByJobDeptno_ARGS = "job, deptno";
List getEmpsByJobDeptno(String job, Integer deptno);

void insert(Emp emp);
void update(Emp emp);
void delete(Emp emp);
}

それではさっそくコンポーネントの定義です。えっ。これだけですか。

<component class="EmpDao">
<aspect>
<component class="org.seasar.s2dao.interceptors.S2DaoInterceptor">
</aspect>
</component>
EmpDao#getAllEmps()を実行すると次のようなSQL文が発行されます。
OUTER JOINの構文は、RDBMSを自動的に判定して組み立てます。

SELECT emp.empno, emp.ename, emp.job, emp.deptno, dept.dname AS dname_0
FROM emp LEFT OUTER JOIN dept ON emp.deptno = dept.deptno
EmpDao#getEmpByEmpno(7788)を実行すると次のようなSQL文が発行されます。
7788の部分は実際はバインド変数が使われます。

SELECT emp.empno, emp.ename, emp.job, emp.deptno, dept.dname AS dname_0
FROM emp LEFT OUTER JOIN dept ON emp.deptno = dept.deptno
WHERE emp.empno = 7788
EmpDao#getEmpsByJobDeptno(null, null)を実行すると次のようなSQL文が発行されます。

SELECT emp.empno, emp.ename, emp.job, emp.deptno, dept.dname AS dname_0
FROM emp LEFT OUTER JOIN dept ON emp.deptno = dept.deptno
EmpDao#getEmpsByJobDeptno("CLERK", null)を実行すると次のようなSQL文が発行されます。

SELECT emp.empno, emp.ename, emp.job, emp.deptno, dept.dname AS dname_0
FROM emp LEFT OUTER JOIN dept ON emp.deptno = dept.deptno
WHERE emp.job = 'CLERK'
EmpDao#getEmpsByJobDeptno(null, 30)を実行すると次のようなSQL文が発行されます。

SELECT emp.empno, emp.ename, emp.job, emp.deptno, dept.dname AS dname_0
FROM emp LEFT OUTER JOIN dept ON emp.deptno = dept.deptno
WHERE emp.deptno = 30
EmpDao#getEmpsByJobDeptno("CLERK", 30)を実行すると次のようなSQL文が発行されます。

SELECT emp.empno, emp.ename, emp.job, emp.deptno, dept.dname AS dname_0
FROM emp LEFT OUTER JOIN dept ON emp.deptno = dept.deptno
WHERE emp.job = 'CLERK' AND emp.deptno = 30
EmpDao#insert()を実行すると次のようなSQL文が発行されます。

INSERT INTO emp(empno, ename, job, deptno)
VALUES(emp.empno, emp.ename, emp.job, emp.deptno)
EmpDao#update()を実行すると次のようなSQL文が発行されます。
emp.*の部分は実際はバインド変数です。

UPDATE emp SET empno = emp.empno, ename = emp.ename,
job = emp.job, deptno = emp.deptno
WHERE empno = emp.empno
EmpDao#delete()を実行すると次のようなSQL文が発行されます。
emp.*の部分は実際はバインド変数です。

DELETE FROM emp
WHERE empno = emp.empno
このような開発者の心(method signature)を読んでSQLを自動生成する機能は
S2Daoのうりの1つです。
自動生成の法則の説明はまた後で。