Top Banner

Click here to load reader

of 26

MVC for Desktop Application - Part 4

Jan 13, 2017

Download

Technology

Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript

Introduction to MVC for Desktop ApplicationCourse C1001He Shiming 2010-9

1

MVC in Windows Desktop Application with Cross-Platform Considerationideal desktop application development

Obviously:MFC is not a good architecture/standardMost likely, there isnt such an ideal architecture, like the Rails framework, or even something close to CocoaWindows API and C++ isnt helping that much on architecture of productsThe hard work has to be done by ourselves

3

Revised MVC Architecture for UsControllerViewModelData

4

Revised MVC Architecture for UsModel represents information, an underlying file format, database connections and queriesView represents user interface, the window and displayed content designed by application logicController is the action processor, responding to command sent from views, pick the right model to process it, and update views to reflect action result

5

An Example, Redesigning Notepad

6

An Example, Redesigning NotepadFrame is the same (this is the root view):

class CMainFrame: public CFrameWindowImpl{public: CEdit m_edit;

BEGIN_MSG_MAP(CMainFrame) MESSAGE_HANDLER(WM_CREATE, OnCreate) MESSAGE_HANDLER(WM_SIZE, OnSize) COMMAND_ID_HANDLER(ID_FILE_NEW, OnFileNew) COMMAND_ID_HANDLER(ID_FILE_OPEN, OnFileOpen) COMMAND_ID_HANDLER(ID_FILE_SAVE, OnFileSave) END_MSG_MAP()...

7

An Example, Redesigning NotepadWM_CREATE handling is the same (still a part of view):

LRESULT CMainFrame::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled){ m_edit.CreateWindow(m_hWnd, WS_CHILD|WS_VISIBLE|...

WM_SIZE too (another part of view)

LRESULT CMainFrame::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled){ RECT rc_client; GetClientRect(&rc_client); m_edit.SetWindowPos(NULL, &rc_client...

8

An Example, Redesigning NotepadBefore we go further, we research and design this application, in other words, well decide what controller does and what model does

9

An Example, Redesigning NotepadWe knew that Notepad should be able to process text files, so we should have a TextFile class that handles reading and writing, this would be a single threaded, static class whose only job is to accept a file name, and return std::wstring to us (this is a model)

10

An Example, Redesigning NotepadSo we have:

class TextFile{public: static bool ReadFile(const wchar_t* filename, std::wstring& content_out); static bool WriteFile(const wchar_t* filename, const wchar_t* content_in);};

11

An Example, Redesigning NotepadWe knew that user may issue command such as OpenFile, SaveFile, NewFile, so we design a FileController class that has these methodsAdditionally, this controller should have a buffer that maintains the current displayed text for editing (for use with views), thus we should have methods such as SetContent, and GetContentTo deal with large files and potential slowness in networked opening, we may need to make OpenFile, SaveFile asynchronized, therefore we may need a method named IsLastFileOpCompleted for views to decide when toretrieve content (this is a controller)

12

An Example, Redesigning NotepadSo we have:

class FileController{public: bool OpenFile(const wchar_t* filename); bool SaveFile(const wchar_t* filename); bool NewFile(); bool SetContent(const wchar_t* content); wchar_t* GetContent(); bool IsLastFileOpComplete();

private: std::wstring m_buffer; // boost::shared_ptr m_fileop_thread; // boost::mutex m_buffer_mutex;};

13

An Example, Redesigning NotepadWhat about views?

LRESULT CMainFrame::OnFileOpen(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled){ CFileDialog fd(TRUE, NULL, NULL, OFN_EXPLORER, L*.txt, m_hWnd); if (!fd.DoModal(m_hWnd)) return 0; if (!m_view.m_filecontroller.OpenFile(fd.m_szFileName)) { MessageBox(LThere is a problem with file opening); return 0; } SetTimer(TIMER_CHECKFILEOPENCOMPLETE, 50); // in WM_TIMER, we check m_filecontroller.IsFileOpComplete() // to decide whether to refresh the m_view using the content // retrieved via m_filecontroller.GetContent...

14

An Example, Redesigning NotepadWe used timed polling to make sure our controller doesnt know any details about views, and is thus directly portableOf course timed polling is bad, it consumes and wastes extra resources while checking for return values, due to the stupidity in its designBut it can be easily controlled, when its required to cancel such a file operation, you kill the timer, and tell the controller to stop file operation

15

An Example, Redesigning NotepadTimed Polling (Timer) versus Mediator/Observer (Java Callback) versus Delegates (C# Callback)Observer pattern should be used in strict sense*MVC is macro-architecture and design pattern is micro-architecture

16

An Example, Redesigning NotepadApplying Observer pattern:

class IFileObserver{public: virtual void SetFileOpComplete(bool iscomplete) = 0;};

class FileObserver: public IFileObserver{public: void SetReceiveWindow(HWND hwnd) { m_hwnd_receive = hwnd; } virtual void SetFileOpComplete(bool iscomplete) { // call SetWindowText depending on |iscomplete|...

Search C++ Interface to learn more about interface classes17

An Example, Redesigning NotepadApplying Observer pattern:

class FileController{public: void AttachObserver(IFileObserver* observer); void DetachObserver();... void _OpenFile_WorkerThread(const wchar_t* filename, bool& ret) { // after file read success m_observer->SetFileOpComplete(true); }...

18

An Example, Redesigning NotepadTo implement multi-tabbing, we put FileController inside CEdit, and replicate CEdit (via std::vector) so that each instance has a controller, a TabController might also be needed to manage tabsTo implement syntax highlight, we implement HiliteNode (base model), HiliteParser (model) that translates wchar_t* string into std::vector, and make sure our FileController can output stuff returned by HiliteParser, then subclass CEdit to implement actual paintingFor unicode BOM, only need to revise TextFile class

19

Redesigning Notepad, What Weve Achieved:Complete isolation of UI and application logicComplete isolation of application logic and low-level data formatsPossible for independent development for most componentsPossible to run unit-test for each components, so that product quality can be assuredPossible to easily port to other platformsClear application logic for future referenceReusable components for future projects

20

Arch. Ver. of Notepad v.s. No-arch. Ver.Primary technical difference is class design, class relation, class differenceUnderlying logic, including frame window management, low-level file reading/writing are mostly the same

21

When Portability is Our Concern:Remember Cocoa/Objective-C is compatible with C++Establish user interface on Cocoa framework like before, the equivalent view on Windows cannot be usedBind Cocoas interface controller actions to our real portable controllersOnly controllers and models can be 100% portable

22

Architecture and MVC is Mostly About:Class design

23

Recommended Readings

References Regarding Design Patternshttp://stackoverflow.com/questions/516411/raw-function-pointer-from-a-bound-method/516537http://stackoverflow.com/questions/946834/is-there-a-design-pattern-that-deals-with-callback-mechanism

25

References Regarding MVC and Othershttp://en.wikipedia.org/wiki/ModelViewControllerhttp://www.oracle.com/technetwork/articles/javase/mvc-136693.htmlhttp://www.djangoproject.com/http://code.google.com/webtoolkit/

26