显示比描述更容易,但应用程序基本上就像一个销售点应用程序,有3个主要部分:Items,OrderItems和Order.
item类是来自数据存储区的数据.
public class Item : IComparable<OrderItem>,IEquatable<OrderItem> { public Int32 ID { get; set; } public String Description { get; set; } public decimal Cost { get; set; } public Item(Int32 id,String description,decimal cost) { ID = id; Description = description; Cost = cost; } // Extraneous Detail Omitted }
订单商品类是订单上的商品系列.
public class OrderItem : Item,IBillableItem,IComparable<OrderItem>,IEquatable<OrderItem> { // IBillableItem members public Boolean IsTaxed { get; set; } public decimal ExtendedCost { get { return Cost * Quantity; } } public Int32 Quantity { get; set; } public OrderItem (Item i,Int32 quantity) : base(i.ID,i.Description,i.Cost) { Quantity = quantity; IsTaxed = false; } // Extraneous Detail Omitted }
目前,当您向订单添加费用或折扣时,它很简单:
Order order = new Order(); // Fee order.Add(new OrderItem(new Item("Admin Fee",20),1)); // Discount order.Add(new OrderItem(new Item("Today's Special",-5),1));
我喜欢它,它是有意义的,并且Order继承自列表中的项目的迭代,计算适当的税收,并允许其他订单类型的文档(其中有2个)从计算的基类继承所有这一切都没有重新暗示任何事情.如果订单类型的文档没有折扣,那就像不添加 – $value OrderItem一样简单.
我遇到的唯一问题是显示这些数据.这种形式有一个网格,其中应显示销售项目(即不是费用/折扣).同样,有一些文本框可以收取某些费用和某些折扣.我非常希望将这些ui元素数据绑定到此类中的字段,以便用户(和我)更容易.
我的想法
有2个接口:IHasFees,IHasDiscounts并且有Order实现它们;两者都有一个List的成员.这样,我只能访问Sale项目,只能访问费用,只能访问折扣(如果需要,可以将它们绑定到控件).
我不喜欢它:
– 现在我有3种不同的类添加/删除方法(AddItem / AddFee / AddDiscount / Remove …)
– 我正在复制(三次复制?)功能,因为它们都只是相同类型项目的列表,只是每个列表都有不同的含义.
我在正确的道路上吗?我怀疑这对大多数人来说是一个解决的问题(考虑到这种类型的软件很常见).
解决方法
什么对“业务用户”有意义(如果你有任何这些).
作为一名程序员,你会想要考虑项目,费用,折扣等,因为他们有相似的属性和行为.
但是,就模型而言,它们可能是两个完全独立的概念.有人会在以后来,说“但这没有意义,它们是分开的东西,我需要单独报告它们,我需要在这种情况下应用这个特定的规则来折扣”.
DRY并不意味着限制你的模型,你应该在通过继承或类似事件来分解行为时保持这一点.
在这种情况下使用的具体示例是购物车的示例.程序员的自然想法是使用处于未通状态的订单.这是有道理的,因为它们看起来完全一样.
除了他们不是.它对客户来说没有任何意义,因为它们是两个独立的概念,它只是使设计不那么清晰.
这是一个实践,品味和意见的问题,所以不要盲目跟随网站上发布的建议:)
对于您的具体问题,我使用的系统使用物品,项目折扣(项目的财产)和订单的全球折扣(虽然它不是订单,它是POS收据但它并不重要在这种情况下).
我想原因是,在这些概念背后,物品是库存件的特定实例,它们影响库存量,它们是可枚举的和可量化的.
费用不是.它们不共享大多数属性.
在您的情况下,这可能无关紧要,因为您的域名似乎比这更有限,但您可能想要记住这些问题.