職場で、レガシーなエンタープライズ アプリケーションの開発に取り掛かりましたが、それはまだ生産中であり、設計の悪さと不安定さのためにここ数か月停止しています。
そこで、EF5 の使用を開始し、いくつかの設計パターン/レイヤーをアプリケーションに適用しました。
私が理解するのに苦労しているのは、サービス層が私たちの場合に正確に何をすべきかということです. それは過剰なアーキテクチャになるのでしょうか、それとも不必要な複雑さを追加せずにいくつかの利点を提供するでしょうか?
これまでに得たものをお見せしましょう:
- レガシーデータベースをマッピングするためにEF(POCOを使用したコードファースト)を導入しました(かなりうまく機能します)
- 新しいデータレイヤーで必要なほとんどのもののリポジトリを作成しました(特定の実装、一般的なリポジトリを使用した懸念の分離に関する利点は見られません..)
ここで、特定のケースでは、記事の価格を計算することについてです-arcile から直接、または記事が含まれるグループから価格を取得します (価格が指定されていない場合)。さまざまな価格表 (注文の完全な値に応じて) や、特別価格などを設定できる顧客に応じて、さまざまな価格表が関係するため、より複雑になっています。
だから私の主な質問は、正しい価格を得る責任があるのは誰ですか?
私の考えは次のとおりです。注文は、構成されているアイテムを知っている必要があります。一方、これらのアイテムは価格を知る必要がありますが、注文はアイテムの価格を計算する方法を知っている必要はありません。コストを要約する必要があるだけです。
現時点での私のコードの抜粋:
ArticlePrice (POCO、マッピングはまもなく Fluid API に置き換えられます)
[Table("artikeldaten_preise")]
public class ArticlePrice : BaseEntity
{
[Key]
[Column("id")]
public int Id { get; set; }
[Column("einheit")]
public int UnitId { get; set; }
[ForeignKey("UnitId")]
public virtual Unit Unit { get; set; }
[Column("preisliste")]
public int PricelistId { get; set; }
[ForeignKey("PricelistId")]
public virtual Pricelist Pricelist { get; set; }
[Column("artikel")]
public int ArticleId { get; set; }
[ForeignKey("ArticleId")]
public virtual Article Article { get; set; }
public PriceInfo PriceInfo { get; set; }
}
記事の価格リポジトリ:
public class ArticlePriceRepository : CarpetFiveRepository
{
public ArticlePriceRepository(CarpetFiveContext context) : base(context) {}
public IEnumerable<ArticlePrice> FindByCriteria(ArticlePriceCriteria criteria)
{
var prices = from price in DbContext.ArticlePrices
where
price.PricelistId == criteria.Pricelist.Id
&& price.ArticleId == criteria.Article.Id
&& price.UnitId == criteria.Unit.Id
&& price.Deleted == false
select price;
return prices.ToList();
}
}
public class ArticlePriceCriteria
{
public Pricelist Pricelist { get; set; }
public Article Article { get; set; }
public Unit Unit { get; set; }
public ArticlePriceCriteria(Pricelist pricelist, Article article, Unit unit)
{
Pricelist = pricelist;
Article = article;
Unit = unit;
}
}
PriceService (恐ろしいコードの匂いがします... )
public class PriceService
{
private PricelistRepository _pricelistRepository;
private ArticlePriceRepository _articlePriceRepository;
private PriceGroupRepository _priceGroupRepository;
public PriceService(PricelistRepository pricelistRepository, ArticlePriceRepository articlePriceRepository, PriceGroupRepository priceGroupRepository)
{
_pricelistRepository = pricelistRepository;
_articlePriceRepository = articlePriceRepository;
_priceGroupRepository = priceGroupRepository;
}
public double GetByArticle(Article article, Unit unit, double amount = 1, double orderValue = 0, DateTime dateTime = new DateTime())
{
var pricelists = _pricelistRepository.FindByDate(dateTime, orderValue);
var articlePrices = new List<ArticlePrice>();
foreach (var list in pricelists)
articlePrices.AddRange(_articlePriceRepository.FindByCriteria(new ArticlePriceCriteria(list, article, unit)));
double price = 0;
double priceDiff = 0;
foreach (var articlePrice in articlePrices)
{
switch (articlePrice.PriceInfo.Type)
{
case PriceTypes.Absolute:
price = articlePrice.PriceInfo.Price;
break;
case PriceTypes.Difference:
priceDiff = priceDiff + articlePrice.PriceInfo.Price;
break;
}
}
return (price + priceDiff) * amount;
}
public double GetByPriceGroup(PriceGroup priceGroup, Unit unit)
{
throw new NotImplementedException("not implemented yet");
}
//etc. you'll get the point that this approach might be completely WRONG
}
私の最後の質問は次のとおりです。問題を正しくモデル化するにはどうすればよいですか? 自分のコードをオーバーアーキテクチャにしようとしているというのは正しいですか? 私のサービス層はどのように正しく見えますか? ArticlePriceService や ArticleGroupPriceService などを使用した方がよいでしょうか? しかし、誰がそのピースをつなぎ合わせて正しい価格を計算するのでしょうか? たとえば、「GetPrice」メソッドを持つ OrderItemService の責任でしょうか。しかし、やはり orderItemService は他のサービスについて知る必要があります..
アーキテクチャに関する可能な解決策と、どのオブジェクト/レイヤーが何をするかを教えてください。
さらに情報が必要な場合は、お気軽に追加の質問をしてください!