Initialization
Startup of more complex c++ applications is a problem. As an application developer you often don't have the ability to fix a lot of the issues related to this problem but there's one thing that bothers me a lot, that you, as an application developer can fix, so I decided to write about it a little today. I'll talk a bit about "delayed initialization" today.
Delayed initialization is one of those "unwritten rules" that you can read about on http://developer.kde.org/documentation/other/mistakes.html . In fact this entry should be added there. I don't have enough time but if you do, please try to format it as an entry there.
So how does a typical startup routine in a KDE application looks like? Well, first of all we have some KMainWindow derived class. For the purpose of my brainfarts here, let it be :
class MainWindow : public KMainWindow
int main( int argc, char **argv)
{
....
KApplication a;KCmdLineArgs *args = KCmdLineArgs:: parsedArgs();
MainWindow *window = new MainWindow( args );
a.setMainWidget( window );
window->show();
return a.exec();
}
The only thing that you have to see in this snippet is the fact that the MainWindow (which in some applications is actually a KUniqueApplication derivative or just a QWidget, either way it's the top level application object) is created before the event loop starts with a.exec().This in turn means that before we get at all to the event loop of the application the main object has too be fully constructed. That in turn implies that we want to avoid doing any non-trivial task in the top-level constructor.
So what should you do? It's very simple: delay the construction of anything besides the GUI until the event loop starts. For example here's how our simple MainWindow should look like:
MainWindow::MainWindow()
{
initGUI();
QTimer::singleShot( 0, this, SLOT(initObject()) );
}
void MainWindow::initGUI() { /* Here you construct the widgets. It's very important that each one of those widgets doesn't perform any non-gui related function in the constructor as well. All you want to do here is create the widgets and QObject::connect them to each other / } void MainWindow::initObject() { / This slot will be called as soon as we enter the event loop. In here you put everything else. Restoring values, file reads/writes/parses, document reading/restoring. everything that doesn't simply create a GUI object */ }
Now what this means for users? It means that they will see the GUI for an application almost immediately. The fact that the app isn't yet functional when the GUI shows up doesn't really mean anything, because once you're in the event loop you can let users know you're not ready by either disabling the widgets of showing a progress bar while the app initializes. In most cases neither one will be even necessary as no one will start clicking right away on the app when it shows up. But it will have the cool effect of making your application seem a lot faster even though you haven't done any real code optimizations :)