Exercise: Applying SOLID principles

The Code has the following behaviour:

  • Books can be added to the basket
  • Basket calculates the total price with no discounts
  • Basket calculates discounts for IT and Travel books
  • Tests are provided for the current functionality

Requirement: Give 20% discount for each Fantasy book when more than one is in the basket.

Proposed refactoring:

  • Transform the books List in a First Class Collection called Books:
    • Move respective behavior to it.
      • Questions about books, number of book types, sum of prices, etc
  • Extract discount offers from Basket
    • Each discount type should have its own class
    • Discount classes should implement the same interface
    • You may need a NoDiscountsBook class to cater for books with no discounts
  • Create a DiscountCalculator that contains a list of discount classes
    • Iterates through discount classes and calculate price with discounts
  • Pass the DiscountCalculator into the Basket constructor
    • Basket delegates discount calculation to DiscountCalculator

Implementing the requirement

  • Test-Drive the Fantasy Book discount offer
  • Create the basket adding the Fantasy discount offer to it.

Lesson:

  • New features can be slid into the code almost without change
    • Minor change on DiscountCalculator and NoDiscountBooks
  • Changes while adding new functionality are small and localised
  • Changes happen in the main (application assembly) and not in the domain
    • This would happen if using Dependency Injection frameworks