In a complex giant patcher, the initialization gets quite complex. The method I settled on, in the largest patch that I use, is to start a metro/counter at the top left corner of the top level patch that counts to 100 at a rate of 5ms / tick. I send this value around via a [send load_percent] and elsewhere in the patch I compare load_percent to some threshold, and initialize when load_percent has crossed that threshold. This allows me a deterministic order of initialization across a giant patch, albeit at the cost of a half second longer load time.
I don't understand why having the delay built into loadbang would be any better than using a delay object. (That's what it's made to do: delay a bang.)
A different approach would be to use a single loadbang at the top level and use send or forward to send the messages you want where you want in the order you want. What with all the objects such as b, t, delay, pipe, uzi, etc., you can construct about any sort of ordering system you want. Here's a ludicrous example.
I wrote a little abstraction to do delayed loadbangs.
The first (optional) argument specifies a delay time in ms. (Optional)arguments after the first one will be sent out as a message after the delay (so it's loadbang and loadmess with a delay function).
Stick it in a patcher, save it as 'loadbangdelay' (that's how I named it anyway) and put it in the Max path.
Be prepared to discover that this scheme (delaying loadbangs) not always works flawlessly. What I found to work better is that a process which has finished (eg loading a file, filling a buffer) triggers the next step in the sequence. And I use deferlow abundantly. The scheduler's ways are unfathomable (sometimes).
For me Initialization order is the most tricky and mysterious part of Max.
In particular, I wonder how to handle self-initializing live.* objects in combination with loadbang initializations of other objects.
i used to think i had a pretty good handle on max initialisation, but since m4l and live.* objects came along, the thing is a minefield. every time i do anything i build test patches which give me different results to the last initialisation-test-patches i made.
so, +1 to broc, any comments always good...
(p.s. - gives me great heart to read the great jvkr's comment "The scheduler's ways are unfathomable (sometimes)")...
I think the delay approach is problematic. Generally you should make a clear distinction between startup time and run time which is scheduled time in Max. If you definately want to defer something to the scheduler at startup defer is a better choice.
In complex patchers it is good to only use one loadbang object, connected to a trigger and possibly send/receive so that you can initialize sub-modules of your patch in a deterministic way. This would correspond to writing multiple init functions in a programming language, and call them all from the main function.
jvkr is right:
delayed loadbangs sometimes do not work as exspected, for example
when drawing to lcd or loading files from disk, and mostly when the delay is too short.
so be careful what you do, never forget that maxmp is a young girl.
answer to christopher:
for the same reason why you make abstractions in any other situation.
110.loaddels 400 500 600 700 800 900 1000 is simply less writing compared to
loadbang del 400 del 500 del 600 del 700 del 800 del 900 del 1000 and
(the same is true for ordered loadbangs - see my abstraction attached.)
then a little idea about how to organize/find the required load order.
you are the programmer, you must simply decide and take responsibilty yourself.
what can really help to do so, is that you do not put any loadbangs in your
subpatches (except inside abstarctions, where it is unavoidable), but have
a "loadbang-input" to you bigger subpatches and/or bpatchers, in order to
keep overview and/or control the load order.
important for beginners: do not use delays only because you are unsure how
to organize order. learn how to organize order!
The order in which objects of the same name receive messages is (basically) not deterministic, however using a trigger to invoke separately named objects is. The name would correspond to the submodule being initialized, of course.
I use the word "basically", since the first case would actually depend on creation order which is of course subtle.