The humble object pattern separates complex, important business logic from difficult-to-test interactions such as frameworks, asynchronous execution, user interfaces, and external systems. The extracted component remains testable; the surrounding wrapper coordinates dependencies while containing little or no logic. section 7.1
Use collaborator count and complexity to decide where logic and tests belong:
- Keep domain models and algorithms complex but narrow, with few collaborators; they offer the strongest return from unit testing. section 7.3
- Leave trivial constructors and similarly insignificant code untested when tests would add little regression protection. section 7.3
- Keep controllers wide but simple: orchestrate collaborators and defer complex decisions to extracted components. section 7.6
- Refactor code that is both complex and collaborator-heavy; it combines high maintenance cost with poor testability. section 7.6
Refactoring customer email changes
An initial User class loads users and company data, determines employee status, updates employee counts, and sends messages. Extract the domain operation so User changes email and Company maintains its employee count; use factories to reconstruct objects from database data; then let UserController load objects, invoke the operation, save them, and send the message. Unit-test the extracted behavior with cases for corporate transitions, non-corporate transitions, unchanged types, and unchanged emails. section 7.2 section 7.3
Figure 7.4. The Humble Object pattern extracts the logic out of the overcomplicated code, making that code so humble that it doesn’t need to be tested. The extracted logic is moved into another class, decoupled from the hard-to-test dependency.
Use the figure to contrast overcomplicated code with a thin wrapper and a separate component decoupled from the difficult dependency. section 7.1
