I use C# to write a (hypothetical) application – online store.
I have a database of products, each product has following information associated with it:
- Product Number (required)
- Name (required)
- Price (required)
- Rating (optional)
- Sold Quantity (optional) — this is total sale of this product
I have 4 pages that show filtered list of products. Pages show different information for each product:
- 1st page : PN, Name, Price
- 2nd page : PN, Name, Price, Rating
- 3d page : PN, Name, Price, Sold Quantity
- 4th page : PN, Name, Price, Rating, Sold Quantity
My question is, how do I design data structures to accommodate all my pages with little duplication?
Brute force approach is to create a type for each page:
IList<Product>
IList<ProductWithRating>
IList<ProductWithSoldQuantity>
IList<ProductWithRatingAndSoldQuantity>
later 3 can derive from Product but due to lack of multiple inheritance ProductWithRatingAndSoldQuantity can’t derive from both Rating and SoldQuantity products.
In a dynamic language I would just add whatever fields I need and be happy.
So I could simulate a dynamic-language-approach by storing extra information (rating, sold quantities) in separate dictonaries, e.g.:
{
IList<Product> Products;
IDictionary<Product, Rating> ProductRatings;
IDictionary<Product, SoldQuantity> ProductSoldQuantities;
}
// is equivalent to
IList<ProductWithRatingAndSoldQuantities>
Building a Product structure that includes everything and then pass around a partially initialized object is not a solution I am looking for.
Any suggestions?
Sorry not enough chars to reply in comment.
You should have a single domain object, Product. It would have non-nullable Name and ProductNumber and Price, because you cannot have products that don’t have those things.
Rating should be a nullable, because it is possible to have a Product that does not have a rating. Whether or not a Product has a Rating, it is still always a Product. I’ll leave QuantitySold, because I wouldn’t actually store that as a property of product, I would have Orders and OrderLine collections, and calculate QuantitySold from those (normalisation). However in the absence of those other collections, you could store it as a field on Product. If I was going to do that, it would be a non-nullable integer property, the default being zero.
You only need a single collection to filter, which would be some implementation of IEnumerable or IQueryable or both, most likely you would opt for something like Entity Framework and actually have an ObjectSet but I’d try to keep my design agnostic of what storage method I’m using and work against those interfaces.
You can then query your single collection to identify which attributes are null on the Products in your domain model. Syntax might not be perfect, but nothing Intellisense won’t pick up, I’m a VB guy 99% of the time.
That is pretty much the cleanest possible domain model for what you are after.
Inheritance would be if you had specialised derivatives of Product that have either extra properties or different behaviour. For example, my own system has a base Product class, and a EbayProduct and AmazonProduct entity which both inherit from Product and contain only the extra logic and properties associated with working with those sites. My Product class has about 20 properties – mostly nullable, as when we list products we don’t necessarily have all the information available. Of these 20, the most I display on any one page is about 15. I probably do something similar to what you are trying to do in that I filter out Products that aren’t ready to list yet using the exact method described, i.e. filtering my Products collection for missing fields.