If a framework doesn't give users the right public interfaces to customize behavior, they will eventually treat private methods as binding API (Spree's original OrderContents#add_to_line_item was a canonical example). That kills the maintainer's ability to refactor while keeping backward compatibility. The fix is to expose behavior via encapsulated service objects with a dependency-injection system so users can swap implementations cleanly — gaining testability and upgrade resilience along the way.