Well the warning in the docs is an old one. Crashes caused by modifying the model dB within observer callbacks were so common that it was a major impetus for the v2016 observer overhaul.
So definitely download and read the PDF doc on that overhaul.
But think about generally, an
EntitiesObserver that gets fired when changes are made, which fire the observer because itself makes changes, which fire the observer … etc., … etc. (The “vicious circle” syndrome.)
Just a note to say that although the API doc examples show the subclassing paradigm for observers, in reality all the observer class (since the 2016 overhaul) are abstract. (This means they have no functionality to pass down to subclasses. Ie, all the previously empty callback methods were removed so that the SketchUp API engine can poll observer objects to ask if they respond to each callback. If not, the engine does not call that method for that particular observer. Since method calls eat time, this speeds up the processing of observer calls.)
Also, the various
add_observer attachment methods do not do any type checking to ask if the argument object is a subclass of any particular class. All the object’s callback methods need be is publicly accessible. So this means the observer object can be of any class, or it could be a module with public callback module methods, or even some instance object with dynamically defined singleton callback methods.
I myself have found that the combo-observer module paradigm to be the most useful and easiest to implement. One submodule with most of the observer callback methods all together is easier because you need not pass information back and forth so much. Many times my observer module is the extension submodule itself. (Data can be kept in local objects accessible to many callbacks that are published as being in different observer classes.)
If you will support MacOS where multiple models might be open, then you’ll need to take care to store data in a hash whose keys are model references. On Windows it’s simpler as only 1 model can be open at a time.
There still are times when instantiating an observer object for each open model makes sense. Extension code needs to track these and dispose of their references when the model is no longer open.