Question

Dans mon application, j'ai plusieurs gestionnaires d'événements qui effectuent une certaine action en réponse à des événements d'interface utilisateur tels qu'un bouton cliquer ou la sélection de menu. Le code de ces gestionnaires d'événements ressemble à ceci par exemple:

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.");
    }

}

Ceci est typique de mes gestionnaires d'événements. Je ne code pas les gestionnaires d'événements monolithiques, mais ils "collent" diverses pièces ensemble. J'ai généralement des classes commerciales / services auxquelles l'interface utilisateur a une référence et dans les gestionnaires d'événements que je passe des appels à un ou plusieurs d'entre eux pour effectuer la tâche souhaitée.

Ce que je me demande, c'est que c'est encore trop couplé? Si je voulais transformer cela en une application de ligne de commande, je devrais extraire des bits du code d'interface utilisateur. Dans l'exemple ci-dessus, il y a une action composée en cours, donc je pense que cela devrait ressembler davantage:

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.");
    }

}

Est-ce correct? Dans le code ci-dessus, quelle serait "l'application"? Un contrôleur? Est-ce la bonne abstraction pour cela? Chaque fois que j'ai besoin d'effectuer une tâche dans un gestionnaire d'interface utilisateur, si c'est toujours une ligne unique (en plus d'obtenir des données dans ou hors des zones de texte, etc.) quiconque a un pointeur vers un tutoriel qui couvre vraiment cela (dans n'importe quel langage de programmation )?

De plus, si en fait, vous devez abstraction des actions composées, comment propager les messages d'erreur à l'intérieur de l'abstraction du composé vers l'interface utilisateur? Une hiérarchie d'exception? Exception unique avec code d'erreur?

METTRE À JOUR

Je regarde le modèle de commande qui semble prometteur.

MISE À JOUR 2

En fin de compte, j'ai décidé de refactoriser mon code comme décrit dans l'humble papier de boîte de dialogue dans la réponse acceptée. Ma compréhension est qu'il s'agit d'un modèle de type présentateur de vue de modèle (MVP) et plus spécifiquement une vue passive. Le refactorisation se déroule bien. Il y a des bords approximatifs dans ma compréhension de l'application complète du modèle en ce qui concerne les choses comme afficher des boîtes de message et un fichier ouverte des boîtes de dialogue ou gérer les minuteries d'événements, mais dans l'ensemble, je suis plus heureux avec mon code; Le couplage serré me dérangeait.

J'ai également trouvé ce "paquet": Modèles et pratiques Client du Client du Client des développeurs: Modèle de vue de vue Modèle (MVP) Bundle qui a un exemple de code MVP. C'est un projet Web alors que mon implémentation actuelle est un bureau, mais je suppose que c'est la beauté du MVP, c'est que cela n'a pas d'importance en partie. Une chose que j'ai obtenue était que la dépendance injecte mes objets de couche de service dans le présentateur plutôt que de les new'ing à l'intérieur de ma classe de présentateur.

Pas de solution correcte

Licencié sous: CC-BY-SA avec attribution
scroll top