トップレベルのアイテム(Recipe
)が子(Ingredient
)と1対多の関係にあり、各アイテムが一意の識別子(ID
)を持っているという単純な関係があります。 )。
単純なCRUD操作の場合、フローは次のとおりです。
RecipeService -> RecipeManager -> Recipe
IngredientService -> IngredientManager -> Ingredient
サービス/マネージャークラスを設計するとき、私は2つの主要な決定に苦労しています。
最初:モデルとプリミティブ
関係に影響を与えるアイテムの挿入中に、プリミティブ値またはモデルオブジェクトを提供しますか?例えば:
class IngredientService {
func addIngredientToRecipe(ID recipeID, String ingredientName, int ingredientAmount)
}
対:
class IngredientService {
func addIngredientToRecipe(Ingredient i, Recipe toRecipe)
}
最初のものは増え続ける引数のリストを必要としますが、内部的にルックアップと検証を処理します(レシピが存在するか、どのように取得するかなど)。
2つ目はよりクリーンですが、発信者がすでにレシピを検索し、材料を作成している必要があります。
順列もあります:
class IngredientService {
func addIngredientToRecipe(ID recipeID, Ingredient ingredient)
}
2番目:補助タイプのサービスとマネージャー
サービスは相互に依存できますか、それともマネージャーに直接飛び込む必要がありますか?実装するとしましょう:
func addIngredientToRecipe(ID recipeID, String ingredientName, int ingredientAmount) {
...
}
既存のレシピを検索するとき、RecipeService
またはRecipeManager
を使用する必要がありますか?サービスが単にマネージャーにシャドウ/転送する場合でも、両方にIDベースのルックアップがあると想定しても安全です。
これらの種類早い段階での決定は、良いパターンやスタイルを確立する上で重要だと感じますが、私は、何らかの落とし穴があるかどうかを特定するのに苦労しています。
超迅速な答え。後で拡張するかもしれません。
プリミティブvsモデル
モデルを使用します。メソッド/関数のシグネチャを指定するときに、関数が必要とする情報がわかりません。したがって、すべての情報を含めるのが最善です。たとえば、インターフェイスを作成している場合、サービスの多くのバージョンで一定に保つことができます。
Managers(リポジトリ)とそれらを配置する場所。
リポジトリをサービスに配置しないでください。サービスロジックはべき等に実行できる必要があるため、内部状態に問題があります。これにより、モデルをどこから取得するかという最初の問題も解決されます。
リポジトリからオブジェクトを取得し、それらを1つまたは複数のサービスに渡して操作してから、リポジトリに戻します。
紛らわしいことに、上記のようなこれらのサービスのオーケストレーションは、サービスまたはサービスレイヤー自体である可能性があります。だからルールは絶対間違いではありませんが、あなたはアイデアを得ます。
それ以外の場合は、ADMスタイルのパターンが適切だと思います。パラメータを変更する関数については常に疑問がありますが、新しいオブジェクトを返す関数のスタイルをすばやく変更することで、必要に応じてコードを実際に変更することなく問題を解決できます。