Teeda で Service を使う際の方針
TeedaでService を使う場合で、以下のどちらの案が良いか迷っています。
案1:Serviceメソッドの引数が増えた場合に、Pageクラスを引数にする方法
【特徴】
- DxoはPageとServiceの両方で使うことができる
- Serviceメソッドの引数にEntityは用いない
【メリット】
- Serviceメソッドの引数がPageに統一されてシンプル
【デメリット】
- 更新系の場合、Serviceメソッド内でDxoしてEntityを取得することになる。一方、参照系の場合のServiceメソッドの戻り値をEntityとするとPageクラス内でDxoすることになる。このような場合だと、1つ1つの処理はシンプルであるが、Dxoによるデータ変換処理がPageとServiceの2箇所で使われることになる。このため、コードに属人性がでてしまう。(プログラマーごとにソースコードがばらばらになり易い。)
<<属人性が出るコードの例>>
参照系でServiceの戻り値が次の3通りの選択肢が出てしまう。
1.Serviceの戻り値をドメインモデルにする
2.Serviceの戻り値をプレゼンテーションモデルにする
3.Serviceの戻り値はvoidで、引数で受け取ったPageのプロパティにプレゼンテーションモデルをセットする
※ 上記の選択肢は1番としたいところだが、制約が無いためバラつきが出てしまう
案2:Serviceメソッドの引数が増えた場合に、PageクラスもしくはEntityを引数にする方法
【特徴】
【メリット】
- Dxoをする箇所がPageだけになるので、クラス図的な観点でシンプル
(Serviceメソッド内でDxoしない。)
【デメリット】
- Entityを引数に持つServiceメソッドとPageを引数に持つServiceメソッドが1つのServiceクラスに混在してしまう。
直感的にコーディングしやすいのが案1、アーキテクチャ的にシンプルなのが案2といったところでしょうか。うーん、迷います。
上記の内容のイメージが沸かない人は、サンプルコードを書いてみたので、ぜひ、見てみてください。
※ ただし、Pageクラスの画面項目のプロパティやsetter/getterは省略しています。
案1:Serviceメソッドの引数が増えた場合に、Pageクラスを引数にする方法
○「1.Serviceの戻り値をドメインモデルにする」の場合
class HogeRegisterPage { @Binding public HogeService hogeService; public String doRegister() { hogeService.register(this); return null; } } class HogeSearchPage { @Binding public HogeService hogeService; @Binding public HogeDxo hogeDxo; List<HogeDto> hogeItems; public String prerender() { List<Hoge> hoges = hogeService.findHoges(this); hogeItems = hogeDxo.convert(hoges); return null; } } // ServiceにDxoがDIされているので、ついつい、照会系の戻り値にプレゼンテーションモデルを // 採用してしまうリスクがある class HogeService { @Binding public HogeDao hogeDao; @Binding public HogeDxo hogeDxo; public List<Hoge> findHoges(HogeSearchPage page) { HogeConditionDto hogeConditionDto = new HogeConditionDto(); ... // page.getFuga() などのgetterを使って検索条件をDtoにセット return hogeDao.findHoges(hogeConditionDto); } public void register(HogeRegisterPage page) { hogeDao.insert(hogeDxo.convert(page)); } }
○「2.Serviceの戻り値をプレゼンテーションモデルにする」の場合
class HogeRegisterPage { @Binding public HogeService hogeService; public String doRegister() { hogeService.register(this); return null; } } class HogeSearchPage { @Binding public HogeService hogeService; List<HogeDto> hogeItems; public String prerender() { hogeItems = hogeService.findHoges(this); return null; } } // Serviceの戻り値は、ドメインモデルであるべし、と考える人には受け入れがたいコード class HogeService { @Binding public HogeDao hogeDao; @Binding public HogeDxo hogeDxo; public List<HogeDto> findHoges(HogeSearchPage page) { HogeConditionDto hogeConditionDto = new HogeConditionDto(); ... // page.getFuga() などのgetterを使って検索条件をDtoにセット return hogeDxo.convert(hogeDao.findHoges(hogeConditionDto)); } public void register(HogeRegisterPage page) { hogeDao.insert(hogeDxo.convert(page)); } }
○「3.Serviceの戻り値はvoidで、引数で受け取ったPageのプロパティにプレゼンテーションモデルをセットする」の場合
class HogeRegisterPage { @Binding public HogeService hogeService; public String doRegister() { hogeService.register(this); return null; } } class HogeSearchPage { @Binding public HogeService hogeService; List<HogeDto> hogeItems; public String prerender() { hogeService.findHoges(this); return null; } } class HogeService { @Binding public HogeDao hogeDao; @Binding public HogeDxo hogeDxo; // 一見シンプルだが、出力が分かりにくい //(どのpageのプロパティに値がセットされたが分からない) // メソッドの責務が増加すると単体テストが困難になる public void findHoges(HogeSearchPage page) { HogeConditionDto hogeConditionDto = new HogeConditionDto(); ... // page.getFuga() などのgetterを使って検索条件をDtoにセット page.setHogeItems(hogeDxo.convert(hogeDao.findHoges(hogeConditionDto))); } public void register(HogeRegisterPage page) { hogeDao.insert(hogeDxo.convert(page)); } }
案2:Serviceメソッドの引数が増えた場合に、PageクラスもしくはEntityを引数にする方法
class HogeRegisterPage { @Binding public HogeService hogeService; @Binding public HogeDxo hogeDxo; public String doRegister() { hogeService.register(hogeDxo.convert(this)); return null; } } class HogeSearchPage { @Binding public HogeService hogeService; @Binding public HogeDxo hogeDxo; List<HogeDto> hogeItems; public String prerender() { List<Hoge> hoges = hogeService.findHoges(this); hogeItems = hogeDxo.convert(hoges); return null; } } // Serviceメソッドの引数がPageとEntity が混在するのがイケてない。 // Serviceメソッドの引数に使うPageはプレゼンテーションモデル // ではなくDtoの代替と見なす必要がある。 class HogeService { @Binding public HogeDao hogeDao; public List<Hoge> findHoges(HogeSearchPage page) { HogeConditionDto hogeConditionDto = new HogeConditionDto(); ... return hogeDao.findHoges(hogeConditionDto); } public void register(Hoge hoge) { hogeDao.insert(hoge); } }