I have no other developers to ask for advice or "what do you think - I'm thinking this" so please, if you have time, have a read and let me know what you think.
It's easier to show than describe, but the app is essentially like a point of sale app with 3 major parts: Items, OrderItems and the Order.
The item class is the data as it comes from the datastore.
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
}
The order item class is an item line on an order.
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
}
Currently when you add fees or discounts to an order it's as simple as:
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));
I like it, it makes sense and a base class that Order inherits from iterates through the items in the list, calculates appropriate taxes, and allows for other Order-type documents (of which there are 2) to inherit from the base class that calculates all of this without re-implimenting anything. If an order-type document doesn't have discounts, it's as easy as just not adding a -$ value OrderItem.
The only problem that I'm having is displaying this data. The form(s) that this goes on has a grid where the Sale items (ie. not fees/discounts) should be displayed. Likewise there are textboxes for certain fees and certain discounts. I would very much like to databind those ui elements to the fields in this class so that it's easier on the user (and me).
MY THOUGHT
Have 2 interfaces: IHasFees, IHasDiscounts and have Order implement them; both of which would have a single member of List. That way, I could access only Sale items, only Fees and only Discounts (and bind them to controls if need be).
What I don't like about it: - Now I've got 3 different add/remove method for the class (AddItem/AddFee/AddDiscount/Remove...) - I'm duplicating (triplicating?) functionality as all of them are simply lists of the same type of item, just that each list has a different meaning.
Am I on the right path? I suspect that this is a solved problem to most people (considering that this type of software is very common).