It's a great rule for any metaprogramming task. When writing a macro, or reflective intercession, make it a shim that wraps non-metalevel code, so it's decoupled, testable and yes debuggable.
The rest comes from my small experience, in college we had a project patching java bytecode on the fly, you could generate correct logic at the bytecode level, but you would lose all the benefit of high level language (typechecking, debugging). One team had this excellent idea to just write the smallest bytecode hook/wrapper that would then call normal Java code.