title: Object-oriented checkout process design
body: <p>My colleague and I have been talking for the past 2 hours, trying to work out the best way to design the aspect of our new online shop that deals with a customer's shopping basket, and I'm still not sure that we've come to a great conclusion.</p>
  
  <p>It sounds like a fairly elementary problem, but we've found that actually there is a huge amount of interdependency between different parts of the system.</p>
  
  <p>The parts (so far!) are:</p>
  
  <ul>
  <li>Shopping basket (tracks what products customers have selected to purchase).</li>
  <li>Deals (defines promotions for products such as "Buy 3 of x for £20", or "Buy 2 of x and get 1 free").</li>
  <li>Low order fee (under a certain value, an additional fee is added to the order).</li>
  <li>Shipping fees (based on a series of options).</li>
  <li>Voucher redemption.</li>
  <li>Customer credits (a customer might have a credit on their account, which would be subtracted from the order total).</li>
  </ul>
  
  <p>I'm very nervous about all these objects talking to each other and getting values from one another, then acting on those values. I'm imagining it'll turn into a big, complex, unmaintainable house of cards.</p>
  
  <p>I'm sure that it's bad practise to have the different parts of my system talking directly to each other, let alone allowing them change each other's state (regardless of how they're doing that), as parts of the system end up relying on other parts being in different states when they run, and if they can all talk to each other, I can't be certain something hasn't changed something else I'm relying on.</p>
  
  <p>But there are lots of examples where I can't see any other way. For example:</p>
  
  <ul>
  <li>A "Buy X, get Y free" kind of deal needs to add the Y product to the basket when the customer checks out with X in their basket. So deals effectively looks and AND affects the basket.</li>
  <li>Working out whether to apply a low order fee is based on the value of the products in the basket, but AFTER multibuy discounts (3 for the price of 2, for example). So it needs to look at the basket, while also taking into account the deals.</li>
  <li>The basket also needs to display a total value while the customer is browsing the site, and that total should take into account product-related deals, but nothing else.</li>
  </ul>
  
  <p>How can I achieve this kind of thing, without shooting myself in the foot and writing code that could affect tons of other code in unexpected ways?</p>