When application logic directly performs effects, tests become dependent on shared state and execution order. Separation of concerns keeps responsibilities and effects apart so each part can be understood, replaced, and tested independently. section 15.1.1 section 15.2.1
A practical boundary hides every external subsystem behind an interface. Business logic depends on those interfaces rather than concrete effects, allowing implementations to be replaced without rewriting the logic. section 15.2.1
A separated design follows these constraints:
- Hide each external service behind an interface. section 15.2.1
- Keep business logic free of bare effects and interface-bypassing hacks. section 15.2.1
- Provide mock or stub implementations for testing. section 15.2.1
- Give each test one responsibility and keep tests independent. section 15.1.1
Contained effects versus an intruding effect
A labyrinth generator expressed through a language interface can contain random-number effects within that boundary. A direct IO version can hide an unrelated destructive command alongside the intended work, making the behavior harder to control and test. section 15.2.1
Listing 2.6 A possible free monadic scenario
script :: Language () #1 script = do #2 readThermometer "Garage" readThermometer "Near the road" readThermometer "House" readBarometer "Garage" readBarometer "House" reportTemperature reportAtmospherePressure clearData
Browse a declarative thermometer-and-barometer script whose interpreters can vary independently from the application scenario. section 2.2.3





















