2017-02-24 5 views
1

私は所有しているエンティティを扱うサービスをデカップリングするためのデザインパターンやコンベンションを探しています。テーマの作成を処理するThemeServiceがあるとします。最初はThemeServiceは各ユーザーのUserDataのテーマをそのまま残していますが、要件は変更され、テーマはThemeCollectionなどの他のエンティティによって所有されています。私の問題は、各ThemeServiceは、「所有する」エンティティが何であれ、密接に結合されていることです。例:所有エンティティのサービスをデカップリングするためのデザインパターンは何ですか?

public class ThemeService{ 
    //coupled to UserData 
    createTheme(Theme t, UserData u); 
    getTheme(String name, UserData u); 
    hasTheme(String name, Userdata u); //Theme name unique within a userdata. 
    validateTheme(Theme t, UserData u); //unique name per user, valid colors, etc. 
} 

public class UserDataService{ 
    ThemeService tService; //component for themes 

    getUsername(UserData u); 
    addTheme(Theme t, UserData u){ tService.createTheme(t, u); } 
    getTheme(String name, UserData u){ tService.getTheme(name, u); } 
    hasThemes(String name, UserData u){ tService.hasTheme(name, u); } 
} 

今すぐThemeServiceはUserDataに密接に結合されています。要件がこれまでに変更とテーマが別のエンティティに属することができた場合は、ThemeCollectionは例えば、私は本当にThemeServiceからのコードの多くを再利用することはできませんし、今ThemeCollectionのもののためのより多くのコードが必要です。

public class ThemeService{ 
    //...continued or in another ThemeService class... 
    createTheme(Theme t, ThemeCollection c); 
    getTheme(String name, ThemeCollection c); 
    hasTheme(String name, ThemeCollection c); 
    validateTheme(Theme t, ThemeCollection c); 
} 

public class ThemeCollectionService{ 
    ThemeService tService; 

    getCollectionName(ThemeCollection c); 
    addTheme(Theme t, ThemeCollection c){ tService.createTheme(t, c); } 
    getTheme(String name, ThemeCollection c){ tService.getTheme(name, c); } 
    hasThemes(String name, ThemeCollection c){ tService.hasTheme(name, c); } 
} 

Iをそれは "Themeable"のようなものを実装する汎用パラメータを取るように誘惑されるでしょう。しかし、エンティティはインターフェイスを実装するだろうという。

public class ThemeService{ 
    createTheme(Theme t, Themeable owner); 
    getTheme(String name, Themeable owner); 
    hasTheme(String name, Themeable owner); 
    validateTheme(Theme t, Themeable owner); 
} 

@Entity 
public class UserData implements Themeable{ 
    getUsername(); 
    getThemes(); //From Themable 
} 

@Entity 
public class ThemeCollection implements Themeable{ 
    getUsername(); 
    getThemes(); //From Themable 
} 

私はそのはず、私のエンティティクラスのビジネスロジックをしたくないので、私はテーマに対応インターフェイスで作成、取得、検証、などは含まれていませんうまくいけば、純粋なデータ構造(モデル内のビジネスロジックがロバートマーティンの「クリーンコード」によればうっすらで、私はいくつかの標準を守ろうとしています)です。

これをデカップリングするための標準的な方法、パターン、コンベンションなどがありますか?私は多かれ少なかれ「大丈夫」か、それともプロダクション環境でぶつかるのですか?私は "仕事を終わらせる"というコードから、モジュール化して再利用可能なコードに向かっています。だから、どんな助けと指針も大変ありがとうございます。

編集:「サービスが2つのエンティティに結合されているのはなぜですか?」

私は所有エンティティと所有エンティティを一緒に「ステッチ」する場所が必要です。例えば、UserDataのためcreateTheme:

public void createTheme(Theme t, UserData u){ 
    entityManager.persist(t); 

    if(!hasTheme(t.name(), u){ 
     u.getThemes().add(t); 
     entityManager.merge(u); 
    } 
} 

だから、この関数は、UserDataのに結合され、かつ任意の同様の「テーマの所有者は、」類似したコードを持っているでしょう。

+0

サービスが2つのエンティティに結合されているのはなぜですか?あなたはこれの理由を明らかにするためにいくつかのコードを投稿できますか? –

+0

@NiklasP質問の最後に短いスニペットを追加しました。 – GuitarStrum

+0

これは疑問にはあまり答えません。本当に 'UserData'が本当に**が' Theme'を所有しているのであれば、なぜ新しいテーマを追加するには 'UserData'エンティティを更新する以外のことがありますか?あなたが言及した 'ステッチング'はおそらく 'UserDataService'で行われるべきです。 – crizzis

答えて

1

良いアプローチは、テーマコレクションの概念をユーザーから分離することです。そして、あなたが持っている:これらの方法で

Class Theme 
Class ThemeCollection //all theme managment things go here 
Class UserData //has a member of type ThemeCollection 

を、テーマの管理に関連するfunctionalitesはThemeCollectionであり、異なるエンティティ間で共有することができます。

+0

私の問題は、ThemeCollectionも単なるデータ構造であることです。 ThemeCollectionは、ServiceLayerがデータ構造から抽象化した自身を保持し、その所有者をマージする方法を知る必要があります。 ThemeCollectionをデータベース側の所有者にステッチするサービスは、それをマージするためにオーナーを知っていなければならないカップリングの問題を抱えています。 – GuitarStrum

+0

ThemeCollectionに新しいテーマを追加するとき、所有者はそれ自身を更新する必要はありません。それはすでにThemeCollectionとの関係を維持しており、その内部に何があるか気にしないためです。 ThemeCollectionのみがマージされます。 – sara

+0

はい、以前のコメントで意味していたことは、ThemeCollectionがThemeが入っていたのと同じ位置にあるということです:ThemeCollectionは、今後UserDataと潜在的に他のエンティティに結び付けられる必要があります。 – GuitarStrum

関連する問題