Goya

Goyaなんですけども。WEB+DBプレスを読みつつ整理。

Serviceクラス

  • プレゼンテーション層
  • サービス層
  • ドメイン
    • Entity
    • Dao
    • Logic/Rule

の3つに分かれますね。

Actionてのはプレゼンテーションフレームワークに依存する所となるでしょう。メソッドの戻り値はString限定、引数はなしよ、とか。前にS2Axisで遊んだ時、例外をAxisの例外クラスに変換して返してやんなきゃいけなかったり。これは判る。

で、Serviceクラスはそう云ったUIの実装から独立させたい。でも明示的にそうは書いてない。

なんでそんな事考えてるかと云うと、以前の案件で、BtoC的注文受付をHTMLベースのWEBアプリで、商品管理や売上実績の管理なんかをWindowsフォーム使ったC/Sで、って形で2本立てでやった事があって、見事にWEBとC/Sで同じ業務ロジックが分散しちゃったんですね。自分の名誉のために云うと、俺は納期ギリギリになっての助っ人要員でしたのよ!あくまでも。

で、同じような事やるなら、C/SじゃなくてWEBサービスでつなげるか、クライアントをSwingで作ってRMIでつなげるって形にしたいのです(S2RMIとかで遊んでるのはそう云うわけです)。でWEBアプリとクライアントアプリ、両方で同じ機能がもしあったら、同じServiceを叩くようにしたいのが人情。UI実装依存の部分はActionクラスで吸収、取り敢えず俺ルール。RMIの場合は直接Service叩いちゃおうかな。

ServiceとLogic

くーすにおけるLogicクラスがServiceクラスになった感じですね。

じゃあGoyaにおけるLogicクラスって何かと云うと、Serviceを構成する更に粒度の細かい処理になるのかなと。くーすで補助ロジックとかそんな名前で呼ばれてた奴に当たるのかな。WEB+DBプレスのサンプルだとここらがなかったのであれですが。

例えば。仕入に対する支払による消込、うーん、「仕入支払」なんて名前にしようか。これを行うには、仕入データの消込ステータスの更新と、支払テーブルに新規レコード追加をしますわな。ServiceクラスとLogicクラスの関係はこうかな。

  • 仕入支払Service
    • 仕入消込更新Logic
    • 支払データ新規追加Logic
      • 支払テーブルDao

リストの上階層が下階層を呼び出すイメージ。ああでも単純なステータス更新だったらLogicを介さずServiceからDaoを直接叩くのもありなのか。WEB+DBプレスのサンプルだとそんな感じですもんね。

  • 仕入支払Service
    • 仕入テーブルDao
    • 支払データ新規追加Logic
      • 支払テーブルDao

こうか。いや、でも消込って、仕入金額の残と支払金額の残と比較して、消込完了か部分消込か判断したり、ロジックが入るから上の直接叩きはやっぱりなし。S2Buri使うとまたここらへんは変わりますね。

で、別のServiceで、今度は「売上返金」みたいなのがあるとする。あらかたの売上は入金で綺麗に消込済みなんだけど、返品売上の明細だけが残っちゃって、残がマイナス。そのまま取引が停止したり長い事取引が無くて、未来の売上との相殺があるかどうか判らんって場合に、取り敢えず債権残を綺麗にしたいなんて時によくある。これは売上の消込(場合によっては請求の消込)と、支払データ新規追加をやらんといかんよな。

  • 売上返金Service
    • 売上消込更新Logic
      • 売上テーブルDao
    • 支払データ新規追加Logic
      • 支払テーブルDao

支払データ新規追加Logicを使い回せる。

こんなイメージかな。Serviceクラスは複数の業務ロジック・業務ルールを束ねて、ひとつのアクティヴィティ(おしごとシートですな)にする役目。例が雑だけども。

で、リッチなドメインモデルって奴だと、LogicクラスはEntityクラスのメソッドとなる訳ですね。多分。

DTOをどこまで食い込ませるか

ここまでは自分なりに思い込みながらすっきりしてるんですが、例えば受注の登録とか、マスタメンテとか、取得するデータが単純な場合は判るんですよ。

ただ、ずっと債権債務関連の画面や帳票を作って来たので、ジョインしまくりUNIONしまくりサブクエリーガンガンなSQLの結果を取りたい場合とかの事をすぐ考えちゃうんですね。それをどうするかが悩み所。

例えば得意先別にこんな項目が横並びになる帳票。

  • A:前月売掛金
  • B:当月入金額
  • C:当月売上金額
  • D:消費税額
  • E:当月売掛金残 (A-B+C+D)
  • F:未決済手形金額
  • G:債権金額 (E+F)

残高テーブル、売上テーブル、入金テーブル、手形テーブルなどなど、色々くっつけまくる訳です。気が遠くなりそうですが、SQL書いてみると結構そんな大変でもないんですよ。もう麻痺してるのかも知れないですが。

SQL嫌いな人って、多分延々と普通のSELECT文とUPDATE文とINSERT文を書いててやんなちゃってんじゃないかなあ。そう云うのはほら、もうS2Daoまかせですから。上の奴みたいなの取って来るSQL作るの、楽しいよ。綺麗に設計してコーディング出来た時と同じくらい楽しい。頭がほぐれて気持ちいい。帳票大好き。それなりに経験年数があるのに、SQL嫌い、書くのを避けたいって云う人が存在する事が最初信じられなかったもん。だから皆毛嫌いしないでガシガシ書いてみたら良いと思う。

話がずれた。

くーすだと、DTOを中心に考えて、DTOに対するDAOを作ってましたよね。あれだとイメージがわきやすいんですけど、さてGoyaですと、サービス層でDxoでEntityからDTOへの変換をする訳です。これは多分、プレゼンテーション要件であるDTOドメイン層にまで持ち込みたくないって事だと思うんですよ。

じゃあ上の奴をどうEntityへマッピングするのかって話で、うわ大変だなーと。S2Dxoがどれだけよろしくやってくれるのかが判らんのですが。どうしたもんか。

  • DB上にビューを作って、それをEntityクラスとマッピング
  • くーすと同じく、DTOドメイン層まで持って行く
  • テーブルと対応したEntityのみを使ってデータを取得、Java側で集計したりくっつけたりしてDTOを作る(Dxoでやる?)

最後のは論外だよなあ、せっかくのRDBMSなのに、自分で処理を書くなんて勿体無い。ビュー案もちょっといいかもと思いますが、俺は素直に上のDTO用のDAOを作っちゃいたい気分かなあ。