Decoupling recipe callbacks into an observer