1) those are notifications for the user, for things like:
"you bought two milks, if you get a third one, we will give you 15% discount" or "you bought three milks, you get 15% discount on them!"
2) Because I don't want to change the state of the ShoppingCart, this is how you lose track of what is actually going on. This allow you to have a very clear separation of what is the original state of the cart, what is the state after we added that.
3) because this is not the new amount, this is a number that you += with the current one, and you will probably do it many times, because each time you modify the cart, you do it using this approach.
How does this model cope with prices changing after they have been added to the customer's cart? Changes, especially increases should perhaps not be reflected. I would store the prices at 'add to cart' time.
I second what Rik said above. You definitely need to preserve price at the time the product was added to the cart, so this is something that the persistence mechanism needs to be aware of.
You might also choose to store a ShipmentMethod here, in that a user could estimate a shipment cost while shopping and have that preserved as they entered checkout. You've already got Discounts here.
And a logical issue just to remember, because I've been burned by it before, is to re-validate the cart upon approaching checkout to ensure that it is still valid (i.e., non-backorderable items are still in stock, etc.).
I believe changing the price after the customer has elected to buy an item would be illegal under UK law, but I'm not qualified in law, so don't take my word for it.
I'm with Diego - neither domain user (store or shopper) thinks of the cart as a set of quantity changes - it's a shopping cart and if they set the value from 5 to 4 they're not thinking -1 and I don't see how this offers any more flexibility. It sounds more likely that it could be a cause of confusion for devs/reporting etc.
I also don't see what ID/token you have for the cart to either associate it with a currently-unknown user (session id) or logged in user (user id).
I would also add an added date or price even though this is just a cart - some people leave carts build up for days and you at least need to let them know the price has changed since they added it.
What I do usually, is to keep messages out of the cart and have it as simple as possible. Business rules as to whether apply discounts on the item, on the whole cart content, free delivery and so on, usually need a full inspection on the cart, the user etc...
So when I want to show messages, I do a conversion from cart to order and apply all the rules in this conversion. Every applied rule has some kind of semi intelligent message attached to it and saves this message in the line item. That way I have everything in one place and I don't have to constantly sync the cart with reality. I also have the guarantee that what I present the user will later show 1:1 in the purchase.
Maybe your CartView is something similar?
This doesn't take into account the kind of messages like 'if you add x, you'll get y', that clearly belong into the cart domain.
I also do not see the use of the ChangeItemQuantity. I'd rater use a LineItemAdd and let it decide to whether change quantity or add new lines. But this might be a bit up-frontey.
I agree with prior statements however. The name MessagePriority is a bit misleading (as I don't see Discount being a priority). You should rename it to something like MessageType. Or remove the Discount from the enum (as you already have discount classes associated with items).
If you need to keep the shopping history, why not use ItemAdded/ItemRemoved records instead of ChangeItemQuantity? It will be more similar to real world.
Message Priority - looks like a kind of logging library. Error/Warning/Notification- is user supposed to see errors in his basket? Discount - that's a different story, as it clearly states the message is about discount. What other messages do you have? ItemUnavailable/OutOfStock, SpecialOffer - and so on. Think about real world.
Discounts. You have two ways of telling customers about discounts - by using the Discount class, or by adding Messages with Priority = Discount. Is there any reason?
In real world we have to pay for the items we buy. Where are the prices?
I think you should store copies of the products in the cart, the description and price is important.. if this can change between the user adding to the cart and checking out, I think its a little weird..
What about having an immutable cart instead if you wanted to track how the user used the cart? this way your cart itself isn't aware of state changes.. and you can have a CartSession that keeps track of all the carts..
I worked for a major online retailer for short time.
Discounts are where the world is complicated, because they come in all shapes a sizes.
Free shipping if you spend $100
Free shipping on televisions
Free upgrade to 2nd day shipping
10% off if you spend over $100
5% off if you spend over $50
$25 off if you use paypal and order more than $200
Discounts are sometimes stackable.
You need a list of discounts that apply, and a rules engine to process them. Now granted, you are just creating a sample, but in the real world that and the whole notion of adding properties to items so you could easily search for ruby earrings in a silver setting was where all the effort was.
Why do you need to know the original state of the cart? I've never done one but I don't get why this is important.
But if you really need to track changes, why don't you a add a shopping cart into a shopping cart? Every shopping cart could reference the previous shopping cart until you get the first shopping cart.
Something like:
public class ShoppingCart
{
public ShoppingCart PreviousShoppingCart {get; private set;}
...
...
public ShoppingCart Update(Item item, double amount)
{
ShoppingCart newCart = new ShoppingCart();
newCart.PreviousCart = this;
//Handle item and amount changes
...
...
return newCart;
Why are you showing the props and not the methods in the class diagram?
I think it's easier to understand what something does when the representation shows what the entities can do rather/as a complement to it's data. "Domain model vs db scheme".
Price changes whilst in the cart are perfectly valid and legal provided that you inform the user when they next view the cart.
Take amazon's UK help page on pricing as an example:
"Confirming Price
Items in your Shopping Basket will always reflect the most recent price displayed on the item's product detail page. Please note that this price may differ from the price shown for the item when you first placed it in your basket. Placing an item in your basket does not reserve the price shown at that time. It is also possible that an item's price may decrease between the time you place it in your basket and the time you purchase it. "
Some people use their carts as a "wish list" and effectively store what they are going to buy in the future - hence the "save for later" functionality many sites add onto their baskets.
In some countries (like here, Estonia), you have to sell stuff with a price you present it to the customer. Well, cheaper, of course as well but not with higher price. Though e-shops are a bit gray area in that sense.
Regarding the changing prices of shopping cart items, I'm sure I've seen this in at least two places on UK sites:
while booking airline tickets, your price is never guaranteed until you actually submit credit card details
i've had items in an amazon cart change price such that at checkout, it notified me of the update in price (well, it actually said something to the affect of "this item is no longer available at price X")
Imho, as long as the user is aware of the possibility of the price changing before checkout, that's fine.
In my experience, one often has to commit/kick off a number of external processes/transactions when actually checking out, ones that influence the price or possibly influence the price of items one may buy in future - so fixing the price while shopping can cause race conditions.
Andrew
Comment preview
Comments have been closed on this topic.
Markdown formatting
ESC to close
Markdown turns plain text formatting into fancy HTML formatting.
Phrase Emphasis
*italic* **bold**
_italic_ __bold__
Links
Inline:
An [example](http://url.com/ "Title")
Reference-style labels (titles are optional):
An [example][id]. Then, anywhere
else in the doc, define the link:
[id]: http://example.com/ "Title"
> Email-style angle brackets
> are used for blockquotes.
> > And, they can be nested.
> #### Headers in blockquotes
>
> * You can quote a list.
> * Etc.
Horizontal Rules
Three or more dashes or asterisks:
---
* * *
- - - -
Manual Line Breaks
End a line with two or more spaces:
Roses are red,
Violets are blue.
Fenced Code Blocks
Code blocks delimited by 3 or more backticks or tildas:
```
This is a preformatted
code block
```
Header IDs
Set the id of headings with {#<id>} at end of heading line:
## My Heading {#myheading}
Tables
Fruit |Color
---------|----------
Apples |Red
Pears |Green
Bananas |Yellow
Definition Lists
Term 1
: Definition 1
Term 2
: Definition 2
Footnotes
Body text with a footnote [^1]
[^1]: Footnote text here
Abbreviations
MDD <- will have title
*[MDD]: MarkdownDeep
FUTURE POSTS
RavenDB 7.1: Next-Gen Pagers - 4 days from now
RavenDB 7.1: Write modes - 6 days from now
RavenDB 7.1: Reclaiming disk space - 8 days from now
RavenDB 7.1: Shared Journals - 11 days from now
There are posts all the way to Feb 17, 2025
RECENT SERIES
Challenge
(77): 03 Feb 2025 - Giving file system developer ulcer
Answer
(13): 22 Jan 2025 - What does this code do?
Comments
There're 3 little things:
1- I've never seen messages in a shopping cart, maybe because I'm not used to buy online or maybe because I might be thinking in something specific.
2- What is ChangeItemQuantity for? Why don't you just change the quantity?
3- Wouldn't be better to change AmountToChangeQuantity to NewAmount or NewQuantity?
1) those are notifications for the user, for things like:
"you bought two milks, if you get a third one, we will give you 15% discount" or "you bought three milks, you get 15% discount on them!"
2) Because I don't want to change the state of the ShoppingCart, this is how you lose track of what is actually going on. This allow you to have a very clear separation of what is the original state of the cart, what is the state after we added that.
3) because this is not the new amount, this is a number that you += with the current one, and you will probably do it many times, because each time you modify the cart, you do it using this approach.
done a few online carts.. i can see using the message info, but I don't see what the ChangeItemQuantity is for.
How does this model cope with prices changing after they have been added to the customer's cart? Changes, especially increases should perhaps not be reflected. I would store the prices at 'add to cart' time.
I second what Rik said above. You definitely need to preserve price at the time the product was added to the cart, so this is something that the persistence mechanism needs to be aware of.
You might also choose to store a ShipmentMethod here, in that a user could estimate a shipment cost while shopping and have that preserved as they entered checkout. You've already got Discounts here.
And a logical issue just to remember, because I've been burned by it before, is to re-validate the cart upon approaching checkout to ensure that it is still valid (i.e., non-backorderable items are still in stock, etc.).
Rik,
I most places, the price can change while the item is in the shopping cart, only when you actually place the order do you actually set the price.
I believe changing the price after the customer has elected to buy an item would be illegal under UK law, but I'm not qualified in law, so don't take my word for it.
Is the discount always going to be a percentage? I have seen discounts in some online stores that are a fixed dollar amount.
I'm with Diego - neither domain user (store or shopper) thinks of the cart as a set of quantity changes - it's a shopping cart and if they set the value from 5 to 4 they're not thinking -1 and I don't see how this offers any more flexibility. It sounds more likely that it could be a cause of confusion for devs/reporting etc.
I also don't see what ID/token you have for the cart to either associate it with a currently-unknown user (session id) or logged in user (user id).
I would also add an added date or price even though this is just a cart - some people leave carts build up for days and you at least need to let them know the price has changed since they added it.
[)amien
I second Damien and Rik.
But, I didn't get what is the use of ShoppingCartView !!
What I do usually, is to keep messages out of the cart and have it as simple as possible. Business rules as to whether apply discounts on the item, on the whole cart content, free delivery and so on, usually need a full inspection on the cart, the user etc...
So when I want to show messages, I do a conversion from cart to order and apply all the rules in this conversion. Every applied rule has some kind of semi intelligent message attached to it and saves this message in the line item. That way I have everything in one place and I don't have to constantly sync the cart with reality. I also have the guarantee that what I present the user will later show 1:1 in the purchase.
Maybe your CartView is something similar?
This doesn't take into account the kind of messages like 'if you add x, you'll get y', that clearly belong into the cart domain.
I also do not see the use of the ChangeItemQuantity. I'd rater use a LineItemAdd and let it decide to whether change quantity or add new lines. But this might be a bit up-frontey.
I agree with prior statements however. The name MessagePriority is a bit misleading (as I don't see Discount being a priority). You should rename it to something like MessageType. Or remove the Discount from the enum (as you already have discount classes associated with items).
Regards
If you need to keep the shopping history, why not use ItemAdded/ItemRemoved records instead of ChangeItemQuantity? It will be more similar to real world.
Message Priority - looks like a kind of logging library. Error/Warning/Notification- is user supposed to see errors in his basket? Discount - that's a different story, as it clearly states the message is about discount. What other messages do you have? ItemUnavailable/OutOfStock, SpecialOffer - and so on. Think about real world.
Discounts. You have two ways of telling customers about discounts - by using the Discount class, or by adding Messages with Priority = Discount. Is there any reason?
I think you should store copies of the products in the cart, the description and price is important.. if this can change between the user adding to the cart and checking out, I think its a little weird..
What about having an immutable cart instead if you wanted to track how the user used the cart? this way your cart itself isn't aware of state changes.. and you can have a CartSession that keeps track of all the carts..
I worked for a major online retailer for short time.
Discounts are where the world is complicated, because they come in all shapes a sizes.
Free shipping if you spend $100
Free shipping on televisions
Free upgrade to 2nd day shipping
10% off if you spend over $100
5% off if you spend over $50
$25 off if you use paypal and order more than $200
Discounts are sometimes stackable.
You need a list of discounts that apply, and a rules engine to process them. Now granted, you are just creating a sample, but in the real world that and the whole notion of adding properties to items so you could easily search for ruby earrings in a silver setting was where all the effort was.
Why do you need to know the original state of the cart? I've never done one but I don't get why this is important.
But if you really need to track changes, why don't you a add a shopping cart into a shopping cart? Every shopping cart could reference the previous shopping cart until you get the first shopping cart.
Something like:
public class ShoppingCart
{
}
}
Is it a bad idea?
Would love it if you could change Precentage to Percentage. Ta.
Why are you showing the props and not the methods in the class diagram?
I think it's easier to understand what something does when the representation shows what the entities can do rather/as a complement to it's data. "Domain model vs db scheme".
Price changes whilst in the cart are perfectly valid and legal provided that you inform the user when they next view the cart.
Take amazon's UK help page on pricing as an example:
"Confirming Price
Items in your Shopping Basket will always reflect the most recent price displayed on the item's product detail page. Please note that this price may differ from the price shown for the item when you first placed it in your basket. Placing an item in your basket does not reserve the price shown at that time. It is also possible that an item's price may decrease between the time you place it in your basket and the time you purchase it. "
Some people use their carts as a "wish list" and effectively store what they are going to buy in the future - hence the "save for later" functionality many sites add onto their baskets.
In some countries (like here, Estonia), you have to sell stuff with a price you present it to the customer. Well, cheaper, of course as well but not with higher price. Though e-shops are a bit gray area in that sense.
Regarding the changing prices of shopping cart items, I'm sure I've seen this in at least two places on UK sites:
while booking airline tickets, your price is never guaranteed until you actually submit credit card details
i've had items in an amazon cart change price such that at checkout, it notified me of the update in price (well, it actually said something to the affect of "this item is no longer available at price X")
Imho, as long as the user is aware of the possibility of the price changing before checkout, that's fine.
In my experience, one often has to commit/kick off a number of external processes/transactions when actually checking out, ones that influence the price or possibly influence the price of items one may buy in future - so fixing the price while shopping can cause race conditions.
Andrew
Comment preview