На работе меня бросили в разработку устаревшего корпоративного приложения, которое все еще находится в разработке и остановилось в течение последних нескольких месяцев из-за плохого дизайна и нестабильности.
Итак, мы начали использовать EF5 и применять некоторые шаблоны / слои проектирования к нашему приложению.
Я изо всех сил пытаюсь понять: что именно должен делать уровень сервиса в нашем случае? Будет ли это чрезмерной архитектурой или принесет некоторые преимущества без добавления ненужной сложности?
Давайте покажем вам, что у нас есть на данный момент:
- мы ввели EF (Code First with POCOs) для сопоставления нашей устаревшей базы данных (работает достаточно хорошо)
- мы создали репозитории для большинства вещей, которые нам нужны на нашем новом уровне данных (конкретные реализации, я не вижу каких-либо преимуществ в отношении разделения проблем с использованием общих репозиториев ..)
Теперь в конкретном случае речь идет о расчете цен на товар - либо путем получения цены напрямую из 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 и т. Д.? Но кто бы мог соединить эти части и рассчитать правильную цену? Было бы, например, быть ответственностью OrderItemService, у которого есть метод GetPrice? Но опять же, orderItemService должен знать о других сервисах.
Пожалуйста, попытайтесь предоставить мне возможные решения относительно архитектуры и того, какой объект / уровень что делает.
Не стесняйтесь задавать мне дополнительные вопросы, если вам нужна дополнительная информация!