Exercise 3: Why Open/Closed Depended on Single Responsibility Already Holding — Possible Solution ==================================================================== WHAT PricingEngine'S OWN SINGLE RESPONSIBILITY ACTUALLY IS ------------------------------ This chapter's own PricingEngine has exactly one job: delegate to whatever strategy it was given. It doesn't calculate anything itself, format anything, log anything, or touch storage - which is precisely why extending DiscountStrategy with a new subclass never required touching it. PricingEngine's own reason to change is "the way pricing gets delegated changes" - and nothing about adding a new discount TYPE touches that. WHAT WOULD HAVE GONE WRONG IF PricingEngine WERE BUNDLED LIKE PayrollReportBad ------------------------------ Imagine PricingEngine also bundled unrelated responsibilities the way PayrollReportBad bundled pay calculation and report formatting - suppose it ALSO logged every price calculation to a file and ALSO sent an analytics event. Adding PlatinumDiscount would still technically only require a new DiscountStrategy subclass - but this chapter's own byte-identical verification of PricingEngine specifically would become a much weaker guarantee. A bundled PricingEngine's own logging or analytics code could easily reference the SPECIFIC set of discount types by name (a common real-world temptation - "log which tier was applied" naturally invites a switch statement over discount names) - and the moment that happens, PricingEngine is no longer genuinely closed to modification, because a new discount type WOULD require editing it, just to keep the logging or analytics branch correct. THE UNDERLYING DEPENDENCY BETWEEN THE TWO PRINCIPLES ------------------------------ Open/Closed's own guarantee - "PricingEngine never needs to change when a new discount type is added" - is only actually true if PricingEngine has no OTHER reason hiding inside it that a new discount type could accidentally touch. Single Responsibility is what rules that out: a class with exactly one job has, by definition, no unrelated logic that a seemingly-unrelated change could brush up against. This chapter's own verified byte-identical result for PricingEngine wasn't just luck - it was the direct consequence of PricingEngine already being SRP-compliant before the extension was ever attempted. WHY THIS WORKS AS AN ANSWER ------------------------------ The answer traces exactly what PricingEngine's own single responsibility is, constructs a concrete counter-scenario (bundled logging/analytics) showing specifically how Open/Closed could break without SRP holding first, and identifies the precise mechanism (a class with one job has no unrelated logic for a new extension to disturb) connecting the two principles rather than asserting they're related in the abstract.