Model-View-Controller

The Model-View-Controller (MVC) is one of the classic architectural patterns from the book Pattern-Oriented Software Architecture, Volume 1“. It addresses interactive applications with a  flexible human-machine interface.

 

The MVC divides the program logic of a user interface into separate components model, view, and controller. The model manages the data and rules of the application. The view represents the data, and the controller interacts with the user.

Model-View-Controller

Purpose

  • User interfaces need to be changed frequently
  • Different user interfaces must be supported
  • The data model is stable

Solution

  • The application is divided into the components Model (data model), View (output components), and Controller (input components)
  • Multiple output components can use the same data model

Structure

ModelViewControler

ModelViewControllerCRC

Model

  • The central component of the pattern
  • Contains the data (and the business logic)
  • Is independent of the View and Controller

View

  • Is responsible for the representing of the data and user interaction
  • Observes the Model
  • A View is associated with a Controller to manipulate the Model

Controller

  • Manages one or more Views
  • Accepts user interactions and prepares them for the Model or View
  • Observes the Model
  • Implements the update logic

There are two exciting aspects of the MVC: initialization and user input:

Initialization

The following steps happen during the initialization of the MVC:

Rainer D 6 P2 500x500

 

Rainer D 6 P2 500x500Modernes C++ Mentoring

  • "Fundamentals for C++ Professionals" (open)
  • "Design Patterns and Architectural Patterns with C++" (open)
  • "C++20: Get the Details" (open)
  • "Concurrency with Modern C++" (open)
  • "Generic Programming (Templates) with C++": October 2024
  • "Embedded Programming with Modern C++": October 2024
  • "Clean Code: Best Practices for Modern C++": March 2025
  • Do you want to stay informed: Subscribe.

     

    • The model is created, and it initializes its data
    • The view is created and observes the Model
    • The controller is created and gets references to the model and the view; it observes the model
    • The application starts event processing

    User Input

    In case of a user event, the following steps happen:

    • The controller accepts the user input, handles them, and triggers the model
    • The model changes its internal data
    • The model notifies all views and controllers about the change of the internal data
    • The views and controller update themself
      • If the PIN is entered incorrectly in an ATM for the third time, this can mean: The display shows that your account is locked. The ATM confiscates your debit card
    • The controller continues to process events

    Example

    The following program mvc.cpp applies the MVC.

    // mvc.cpp
    
    #include <iostream>
    #include <string>
    #include <unordered_map>
    
    
    class DefectModel {
     public:                                                                      // (5)
         mutable std::unordered_map<std::string, std::string> defects_ = { {"XYZ" , "File doesn't get deleted."},
                                                                           {"XAB" , "Registry doesn't get created."},
                                                                          {"ABC" , "Wrong title get displayed."} };
    
        std::string getDefectComponent(const std::string& component) const {
            return defects_[component];
        }
    
        int getSummary() const {
            return defects_.size();
        }
    
        std::unordered_map<std::string, std::string> getAllDefects() const {
            return defects_;
        }
    
    };
    
    class DefectView {
     public:
        void showSummary(int num) const {
            std::cout << "Their are " + std::to_string(num) + " defects in total!\n";
        }
        
        void showDefectComponent(const std::string& defect) const {
            std::cout << "Defect of component: " + defect + '\n';
        }
    
        void showDefectList(const std::unordered_map<std::string, std::string>& defects) const {
            for (const auto& p: defects) {
                std::cout << "(" + p.first + ", " + p.second + ")\n";
            }
        }
    };
    
    class DefectController {
        const DefectModel& defectModel;
        const DefectView& defectView;
     public:
        DefectController(const DefectModel& defModel, const DefectView& defView):
                         defectModel{defModel}, defectView{defView} { }
    
        void showDefectComponent(const std::string& component) const {
            defectView.showDefectComponent(defectModel.getDefectComponent(component));    // (6)
        }
    
        void showDefectSummary() const {
            defectView.showSummary(defectModel.getSummary());                             // (7)
        }
    
        void showDefectList() const {
            defectView.showDefectList(defectModel.getAllDefects());                       // (8)
        }
    
    };
    
    int main() {
    
        std::cout << '\n';
    
        DefectModel defectModel;
        DefectView defectView;
    
        DefectController defectController(defectModel, defectView);  // (1)
        defectController.showDefectComponent("ABC");                 // (2)
        std::cout << '\n';
        defectController.showDefectSummary();                        // (3)
        std::cout << '\n';
        defectController.showDefectList();                           // (4)
    
        std::cout << '\n';
    
    }
    

     

    The controller gets its model and view in its constructor (line 1) and displays its defect list defects_ (line 5) in three ways (lines 2 – 4). The controller triggers each call in the function and uses its view to display the data given by the model (lines 6 – 8).

    The following screenshot shows the output of the program:

    mvcExample

    Variation

    Presentation-Abstraction-Control is an additional pattern from Pattern-Oriented Software Architecture, Volume 1“, similar to the MVC.  It used a hierarchical structure of agents, each agent consisting of the presentation, abstraction(model), and data control. The agents communicate with each other through the control.

    Pros and Cons

    Pros

    • Separation of concern: The Model is strictly separated from the Controller and the Views. Therefore, many views or controllers can be supported concurrently and changed at run time.
    • The views as synchronized because they are updated at the same time.

    Cons

    • The MVC may be too complex and overkill for a small human-machine interface.
    • A modification in the model may trigger a cascade of operations on its dependent views and controllers.
    • The view and the controller are strongly coupled. A modification of one of them may break the other.

    What’s Next?

    Event-driven applications, such as GUIs or servers, often apply the architecture pattern Reactor. A Reactor can accept multiple requests simultaneously and distribute them to different handlers.

     

    Thanks a lot to my Patreon Supporters: Matt Braun, Roman Postanciuc, Tobias Zindl, G Prvulovic, Reinhold Dröge, Abernitzke, Frank Grimm, Sakib, Broeserl, António Pina, Sergey Agafyin, Андрей Бурмистров, Jake, GS, Lawton Shoemake, Jozo Leko, John Breland, Venkat Nandam, Jose Francisco, Douglas Tinkham, Kuchlong Kuchlong, Robert Blanch, Truels Wissneth, Mario Luoni, Friedrich Huber, lennonli, Pramod Tikare Muralidhara, Peter Ware, Daniel Hufschläger, Alessandro Pezzato, Bob Perry, Satish Vangipuram, Andi Ireland, Richard Ohnemus, Michael Dunsky, Leo Goodstadt, John Wiederhirn, Yacob Cohen-Arazi, Florian Tischler, Robin Furness, Michael Young, Holger Detering, Bernd Mühlhaus, Stephen Kelley, Kyle Dean, Tusar Palauri, Juan Dent, George Liao, Daniel Ceperley, Jon T Hess, Stephen Totten, Wolfgang Fütterer, Matthias Grün, Phillip Diekmann, Ben Atakora, Ann Shatoff, Rob North, Bhavith C Achar, Marco Parri Empoli, Philipp Lenk, Charles-Jianye Chen, Keith Jeffery, Matt Godbolt, and Honey Sukesan.

    Thanks, in particular, to Jon Hess, Lakshman, Christian Wittenhorst, Sherhy Pyton, Dendi Suhubdy, Sudhakar Belagurusamy, Richard Sargeant, Rusty Fleming, John Nebel, Mipko, Alicja Kaminska, Slavko Radman, and David Poole.

    My special thanks to Embarcadero
    My special thanks to PVS-Studio
    My special thanks to Tipi.build 
    My special thanks to Take Up Code
    My special thanks to SHAVEDYAKS

    Modernes C++ GmbH

    Modernes C++ Mentoring (English)

    Do you want to stay informed about my mentoring programs? Subscribe Here

    Rainer Grimm
    Yalovastraße 20
    72108 Rottenburg

    Mobil: +49 176 5506 5086
    Mail: schulung@ModernesCpp.de
    Mentoring: www.ModernesCpp.org

    Modernes C++ Mentoring,

     

     

    0 replies

    Leave a Reply

    Want to join the discussion?
    Feel free to contribute!

    Leave a Reply

    Your email address will not be published. Required fields are marked *