2

私は貧血のドメインモデルで終わることを避けようとしているので、ドメインモデル自体の中で可能な限り多くのロジックを維持しようとしています。と呼ばれるメソッドがあります。これは、AggregateAddIngredientに新しいものを追加する必要があります。KeyedObjectRecipe

ドメインモデル自体にはリポジトリがないことを意図しているため、ビジネスルールクラスを介して要素を取得しています。

public class Recipe : AggregateObject
{
    public void AddIngredient(int ingId, double quantity)
    {
        GetIngredientMessage message = new GetIngredientMessage();
        message.IngredientId = ingId;

        GetIngredient handler = ServiceLocator.Factory.Resolve<GetIngredient>();
        Ingredient ingredient = handler.Execute(message);

        Ingredients.Add(new OriginalIngredient()
        {
            Ingredient = ingredient,
            Quantity = quantity
        });
    }
}

ご覧のとおり、ビジネスルールクラスServiceLocator.Factory.Resolve<GetIngredient>();を取得するために線を使用しています。次のような単純なコマンドハンドラです。GetIngredientGetIngredient

public class GetIngredient : ICommandHandler<Ingredient, GetIngredientMessage>
{
    private readonly IIngredientRepository _ingredientRepository;

    public GetIngredient(IIngredientRepository ingredientRepository)
    {
        _ingredientRepository = ingredientRepository;
    }
}

IoCファクトリクラスをに割り当てるServiceLocator.Factoryので、ドメインは具体的なクラスの実装を見ることなく、独自のインターフェイスを使用できます。

 ServiceLocator.Factory = new IoCFactory();

すべてが少しボッジのように感じられるので、私は何か間違ったことをしていると確信しています。

  • 誰かが露骨に間違っているものを見つけることができますか?
  • GetIngredientIoCファクトリへの静的参照なしなど、ビジネスルールハンドラをインスタンス化するためのより適切な方法はありますか?
4

1 に答える 1

3

デザインに別のレイヤー、つまりアプリケーションレイヤーを導入することをお勧めします。このレイヤーの責任は、コマンド(コマンドオブジェクトに明示的にカプセル化されているか、として暗黙的に渡されるint ingId, double quantity)をドメインモデルの呼び出し(Recipe.AddIngredient)に変換することです。

そうすることで、IDで成分を見つける責任をドメインの上のレイヤーに移し、不要なカップリングを導入することなく、リポジトリを直接安全に利用できるようになります。変換されたソリューションは次のようになります。

public class ApplicationLayer
{
   private readonly IRecipeRepository _recipeRepository;
   private readonly IIngredientRepository _ingredientRepository;

   /*
    * This would be called by IoC container when resolving Application layer class.
    * Repositories would be injected by interfacy so there would be no coupling to
    * concrete classes.
    */
   public ApplicationLayer(IRecipeRepository recipeRepository, IIngredientRepository ingredientRepository)
   {
      _recipeRepository = recipeRepository;
      _ingredientRepository = ingredientRepository;
   }

   public void AddIngredient(int recipeId, int ingId, double quantity)
   {
       var recipe = _recipeRepository.FindById(recipeId);
       var ingredient = _ingredientRepository.FindById(ingId);
       recipe.AddIngredient(ingredient, quantity);   
   }
}

そして、今では単純化されたRecipeクラスは次のようになります。

public class Recipe : AggregateObject
{
    public void AddIngredient(Ingredient ingredient, double quantity)
    {
        Ingredients.Add(new OriginalIngredient()
        {
            Ingredient = ingredient,
            Quantity = quantity
        });
    }
}

お役に立てば幸いです。

于 2010-09-15T05:16:18.780 に答える