19449


Java / WebApplicationでの話です。

たとえば、DBから、下記のようなDTOコレクションを取得します。

[code]

    public class Model {
        private Long id;
        private String data;
        private Date date;
        private boolean enabled;
    
        ...getter setter略...
    }
    
[/code]

以下、ビジネスロジック例とします。

[code]

    List<Model> entities = modelDao.findAll();
    
[/code]

その後、Date型やBoolean型を正規化し、view用モデルクラスに入れなおします。

[code]

    public class ModelView extends Model {
        private String dateView;
        private String enabledView;
    
        public ModelView(Model model) {
            this.id = model.getId;
            this.data = model.getData();
            this.dateView = DateUtils.format(model.getDate(), "yyyy-MM-dd");
            this.enabledView = model.getEnabled() ? "YES" : "NO";
        }
        .... getter setter略 ....
    }
    
[/code]

上記クラスを使って、

[code]

    List<Model> entities = modelDao.findAll();
    List<NodelView> views = new ArrayList<ModelView>();
    if (entities != null || entities.size() > 0) {
        for (Model model : entities) {
            views.add(new ModelView(model));
        }
    }
    return views;
    
[/code]

というのが一番メモリ的にもパフォーマンス的にもいいのかと思いますが、  
こういったケースで推奨されている実装はあるのでしょうか？

ご回答ありがとうございました。  
まず、Modelクラス内に取得メソッドを、という回答についてですが、  
すみません、前提条件を記載しておりませんでした。

基本的に、リクエストスコープの変数をJSPなりJSTLで出力しようとしていました。  
今回の場合、以下のような形になると想定します。

[code]

    <c:forEach var="o" items="views">
        <c:out value="${o.dateView}" />
        <c:out value="${o.enabledView}" />
    </c:forEach>
    
[/code]

この方法では、getter/setter及び、ローカル変数の定義が必要だったと思います。  
ですが、このModelクラスはSpringJPAのEntity定義に基づいており、  
いろいろDB関連の定義が多く含まれているので、あまり例外的な定義したくありませんでした。

また、JSTLタグlibraryのfmtなどを使う方法もあったかと思いますが、  
個人的な理由ですが、HTML/JSPが好きでなかったため、サーバーサイドでリクエストスコープに置く変数そのものをVIEW用に正規化した状態で持ちたいです。

そのため、  
ListからListに詰め替えるというのは非効率的だし、  
それぞれのセッションが同時にこの関数を実行したときに、メモリの心配もあるなと思い、  
なにかエコな実装があるかなと思った次第でした。


CC BY-SA 3.0
2015-11-28T11:29:32.383
19409
2015-11-30T11:22:12.893
2015-11-30T11:22:12.893
8396
8396
question
java アルゴリズム
Java WEBAppでCollectionの内容物を全て表示用に加工するアルゴリズムについて


背景となる情報が確定すればさらに良い回答があるかもしれません。  
フレームワークやテンプレートライブラリの制約、プロジェクトのコード規約でこのパターンが適用できないこともあると思いますが、  
そもそもビュー用のフィールドではなくメソッドを用意する方法はどうでしょう？  
（下の例のメソッド名は微妙ですけど）

[code]

    public class Model {
        ...各フィールド定義 + getter/setter ...
    
        public String dateView() {
            return DateUtils.format(getDate(), "yyyy-MM-dd");
        }
        public String enableView() {
            return getEnabled() ? "YES" : "NO";
        }
    }
    
[/code]

view的なクラスなら多分、1リクエストで1回しかview用の処理が呼ばれることはないでしょう。  
それならフィールドに保存せずにメソッドを用意しておくと良いと思います


CC BY-SA 3.0
2015-11-29T22:54:59.493
19447
2015-11-29T22:54:59.493
13451
19409
answer


作業効率の面で考えると、JSP＋タグライブラリや、テンプレートエンジン側で出力フォーマットを定義する方が優れているでしょうか。

というのも、JSPを使う場合にはJSTLに代表されるライブラリには、出力フォーマットを定義するタグも、繰り返し要素(CollectionsのListやMapに対応するもの)が用意されており、これは他のテンプレートエンジンも同様です。  
単にString化するのであれば、Javaのコードで記載しても結局同じことをテンプレート側で行うので、パフォーマンスへの影響は大した差になりません。

出力時に何らかの加工をしてから画面に表示したい、具体的にはCollectionに格納した中身そのものを、フォーマット変更だけではなく特定の値に変換するのであれば、JSPやテンプレートエンジンに渡す前に加工するのもひとつの手段として選択できますが、似たような変換を複数の画面、複数の機能で実装するのであれば、やはり出力側の機能として、タグライブラリの追加やテンプレートエンジンの機能を追加しておくと再利用性が期待できます。

他にも表示するために文字列化する処理をDataTransferObjectで行わずView側で行う理由としては、DataTransferObjectのデザインパターンのお作法として、

  * 自身のデータの格納機能（ミューテータ）
  * 自身のデータの取得機能（アクセサ）

このメソッドしか持たない、というものがあるためです。

※もちろんわざわざライブラリ機能に追加してまでやるほどの規模ではない、と判断したならばこのお作法にならうこともないですが。


CC BY-SA 3.0
2015-11-29T23:55:42.127
19449
2015-11-30T07:15:44.037
2015-11-30T07:15:44.037
5778
5778
19409
answer