コンストラクタで複雑な初期化

B15:

私は、さまざまなデータのマップを管理してモデルのようなものを持っています。私は、コンストラクタは、ビジネスロジックを含むべきではないことを読んだが、私はまた、コンストラクタは、彼らがオブジェクトの状態を初期化するために必要なものを行うために自由であることを読みました。どのようなマップA与えられ、コンストラクタでBをマッピングし、あれば、私はそれらの二つのマップをマージすると3番目のフィールドに結果を設定します。たぶん私はまた、いくつかのクリーンアップや何かをしたいです。この悪い習慣はありますか?もしそうなら、なぜですか?

public class MapManager {

    private Map<String, Object> mapA;
    private Map<String, Object> mapB;
    private Map<String, Object> combinedMap;

    public MapManager(Map<String, Object> mapA, Map<String, Object> mapB) {
        this.mapA = mapA;
        this.mapB = mapB;
        this.combinedMaps = initCombinedMap(mapA, mapB);
    }

    public Map<String, Object> getMapA() {
        return mapA;
    }

    public Map<String, Object> getMapB() {
        return mapB;
    }

    public Map<String, Object> getCombinedMap() {
        return combinedMap;
    }

    private static Map<String, Object> initCombinedMap(Map<String, Object> mapA, Map<String, Object> mapB) {
        Map<String, Object> combinedMap = new HashMap<>(mapA);

        if (mapB != null) {
            mapB.forEach(combinedMap::putIfAbsent);
        }

        return combinedMap;
    }
}
ruakh:

私は、コンストラクタは、ビジネスロジックを含むべきではないことを読んだが、私はまた、コンストラクタは、彼らがオブジェクトの状態を初期化するために必要なものを行うために自由であることを読みました。

これらのステートメントの両方が良いアドバイスをしている - そして、彼らは矛盾ではありません。

私は、あなたの質問には、「ビジネスロジック」としてカウントかについて実際にあると思います。一般的な考え方は、ソフトウェア(ない開発者)の実際の「ビジネスクライアントは」のために求めている、または気に可能性があることを行動を意味する「ビジネスロジック」実装「ビジネスルール」、。


たとえば、ビジネスルールは、キリル文字は、ユーザー名に許可されていることを述べていると仮定しない限り、ユーザ名も、ユーザー名内のすべてのキリル文字はラテン語の対応のために間違えやすいものであるラテン文字が含まれ、または(2)(1)のいずれか。(:私は「Веn」という名前のものを作成することによって、「ベン」という名前のアカウントを偽装することはできません、また一つは「Димa」という名前のものを作成することによって、「Димаを」という名前のこのビジネスルールは、なりすましを防ぐことができます。)

さて、あなたはおそらくのようなものというビジネス・ドメイン・オブジェクト・クラス、持っているUserアプリケーションユーザを表し、; あなたは不変のように、このビジネスルールを実装するために誘惑されるかもしれないのでUser、それはのインスタンスを持つことが文字通り不可能だということを意味し、クラスをUserそれは、このビジネスルールに違反します。そのために、あなたは(おそらく何らかのに委任することにより、コンストラクタでこのルールを実装するvalidateUsername方法か何か)。

これで1つの問題は、このルールに違反したユーザー名を持つユーザーを持つように文字通り不可能ではないということです。重要な顧客は、ユーザー名の需要に呼び出した場合сорを、その後、誰かがデータベースにアクセスし、手動でユーザーを作成する必要があるかもしれません-あなたはしたくない、その場合にはUserクラスがあなたからそのユーザーをロードしようとする最初の時間を爆破しますデータベース。

これでもう一つの問題は、ルールが時間をかけてより複雑になるにつれて、あなたはデータベースまたは構成ストアに関連するデータを抽出することになるかもしれないということです、そして、あなたは明らかにだけインスタンス化するために、データベース接続を必要としたくないUserユニットテストで。

より良いアプローチは区別することがあるので、上の技術的な制約Userクラス例えば取り込まれなければならないか、他のものは、変異されてはならないか、他のものは爆破されますフィールドを爆破しますフィールド- -とユーザーアカウントのビジネスの制限クラス自体は厳密には、前者が、後者ではないを強制すべきです。代わりに、ユーザーを検証するための別の方法を持っており、データベースにユーザを追加する前に、そのメソッドを呼び出す必要があります。


残念ながら、私はあなたを理解していないMapManagerことにコメントに十分クラス(と私は実際にそれのように理にかなっていることを少し懐疑的だ凝集クラス)が、それは場合に役立ちます、ここにある初期化ロジックのいくつかの例でありませんが「ビジネスロジック」と見なさ:

  • クラスは、二重リンクリストなどのデータ構造、(表す場合java.util.LinkedList)、ハッシュテーブル(java.util.HashMap)、赤黒木(java.util.TreeMapまたはjava.util.TreeSet場合は特に- )が、絶対にそのコンストラクタは、データ構造を初期化するためのロジックを含むことが予想されます(これらの例はすべてそうであるように)それは既存のコレクションコピーその内容を取るコンストラクタを持っています。ビジネスクライアントはそれらについての意見を持っていないので、これは、「ビジネスロジック」ではありません。彼らはおそらくも、用語「リンクリスト」や「木」を知りません。すべてこれらのクラスについては、「技術」のカテゴリではなく、「ビジネス」に落ちます。
  • クラスがnullにすることになっていない不変のフィールドがある場合、絶対にそのコンストラクタがこれをチェックして調達することが期待されますjava.lang.NullPointerException情報メッセージで。ここでは技術的な実装上のビジネスルールの何らかの影響があるかもしれません-私たちは、「この分野は今、NULL可能でなければならないだろう」と直接、かなり変換し、新たなビジネス要件を想像することができます(実際にかかわらず、別の方法を実装してしまうかもしれませんこと、例えばフィールドを変更してjava.util.Optional、それに依存している下流のコードがありそうだから、それは技術的なルールだ、などのようなものを書く- )this.username.toLowerCase()nullをチェックせずに。(これは、プラグマティズムの問題です;?サポートヌルのユーザー名への書き込み余分なコードは、彼らがしている可能性は低いが今までただ検証の先行投資した方が良いを許可する場合、なぜ。)

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=235962&siteId=1