Chef executes recipes with a two pass model: First it compiles each resource/provider by walking through the run list. Then it converges each of the compiled resource/providers to perform work.
While I (finally) understand how it works; I don't understand the why. It seems like there are quite a few pitfalls w/ this model:
It is very easy to execute tasks out of order by accidentally inlining work (forgetting to use
LWRPs that declare inline resources have a confusingly different execution order (their actions occur in the convergence phase, but any resources they declare get run after the current provider)
It is not very obvious to newcomers.
What are the benefits of this two pass architecture? Why was Chef built this way? (I'm not finding obvious docs on it)