I would say the primary reason for avoiding a macro is about whether you’re generating good Julia code. The rule of thumb is that you almost always don’t need to write a new macro. If you can write better code (less redundant, less names added to global scope, etc) to serve the same purpose without metaprogramming, then don’t do it.
As for it’s difficulty, it’s a bit harder than writing source code. At minimum, you need to understand the structure of Expr and how to manipulate it. You can instantiate Expr with the more readable syntax of source code in quoted expressions, insert things with $-interpolation. You may still have to directly mutate it afterward.
Once you figure that out, you have the option of eval-ing expressions into the global scope, generating them in a macro, or generating them in generated functions. Because macros operate earlier in the parsing phase and can transform code in local scopes, you also have to learn macro hygiene. That’s the short version of what metaprogramming entails.