Question

In my application I have several event handlers that perform some action in response to user interface events such as a button click or menu selection. The code in these event handlers looks like this for example:

void MyDialog::OnCommandLoadFile()
{
    char strFilter[] = { "Text Files (*.txt)|*.txt|All Files (*.*)|*.*||" };

    CFileDialog fileDlg(TRUE, ".txt", NULL, 0, strFilter);

    if( fileDlg.DoModal() == IDOK )
    {
        const std::string path = fileDlg.GetPathName();

        std::vector<std::string> urls;
        int maxNumberOfUrls = settings_->Get<int>(Settings::MaxNumberOfUrls);
        UrlProvider *urlProvider = new FileUrlProvider(path);
        urlProvider->GetUrls(urls, maxNumberOfUrls);

        webMonitoringService_->MonitorUrls(urls);

        DisplayMessage("URLs loaded.");
    }

}

This is typical of my event handlers. I don't code monolithic event handlers but they do "glue" various pieces together. I usually have some business-logic/service classes which the UI has a reference to and in the event handlers I make calls to one or more of these to perform the desired task.

What I'm wondering is is this still too coupled? If I wanted to turn this into a command line app I'd have to extract bits and pieces from the UI code. In the above example, there is a compound action going on so should I'm thinking it should look more like:

void MyDialog::OnCommandLoadFile()
{
    char strFilter[] = { "Text Files (*.txt)|*.txt|All Files (*.*)|*.*||" };

    CFileDialog fileDlg(TRUE, ".txt", NULL, 0, strFilter);

    if( fileDlg.DoModal() == IDOK )
    {
        const std::string path = fileDlg.GetPathName();

        application->MonitorUrlsFromFile(path);

        DisplayMessage("URLs loaded.");
    }

}

Is that right? In the above code what would "application" be? A controller? Is that the right abstraction for this? Whenever I need to perform some task in a UI handler, should it always be a one-liner (aside from getting data in or out of text boxes etc.) Anyone have a pointer to a tutorial that really covers this (in any programming language)?

Furthermore, if in fact you should abstract compound actions, how to you propagate error messages from within the compound abstraction back out to the UI? An exception hierarchy? Single exception with error code?

UPDATE

I'm looking at the Command Pattern which looks promising.

UPDATE 2

In the end I decided on refactoring my code as described in the Humble Dialog Box paper in the accepted answer. My understanding is that this is a Model View Presenter (MVP) type pattern and more specifically a Passive View. The refactoring is going smoothly. There are some rough edges in my understanding of the full application of the pattern when it comes to things like displaying message boxes and file open dialogs or dealing with event timers but overall I'm happier with my code; the tight coupling was bothering me.

I also found this "bundle": patterns & practices Web Client Developer Guidance: Model View Presenter (MVP) Bundle which has sample MVP code. It's a web project whereas my current implementation is desktop but I guess that's the beauty of MVP is that it partly doesn't matter. One thing I got from that was to dependency inject my service layer objects into the presenter rather than new'ing them inside my presenter class.

No correct solution

Licensed under: CC-BY-SA with attribution
scroll top