[wxpython-dev] Google SoC Project - MVC

Kevin Ollivier kevino at theolliviers.com
Fri May 30 13:31:50 PDT 2008


Hi Mike,

On May 30, 2008, at 12:17 PM, Mike Rooney wrote:

> Robin Dunn wrote:
>> Kevin Ollivier wrote:
>>> Hi Peter,
>>>
>>> On May 29, 2008, at 1:57 AM, Peter Damoc wrote:
>>>
>>>> Hi Keith,
>>>>
>>>> My suggestion is to investigate Cells technology (pycells and  
>>>> Trellis) integration with wxPython
>>>
>>> Definitely worth taking a look at, but I think a better approach  
>>> would be to simply allow wxPython controls to take a model and  
>>> controller, and use them when set. This way we're not trying to re- 
>>> invent wxPython or trying to get fundamentally different  
>>> frameworks with different design philosophies and target audiences  
>>> to try and play nice together. We're just extending it to be MVC- 
>>> friendly. We can use something like wx.lib.pubsub to send  
>>> notifications when either the model or the view changes, and the  
>>> controller sets up listeners for these events and handles any  
>>> changes that needs made.
>>
>> I'm not sure how to go about implementing this, but some thoughts  
>> I've had about MVC in wxPython are that it would be nice to be able  
>> to have some sort of modular controller and/or model.  In other  
>> words, each widget involved in the view would have an associated  
>> component that would automatically integrate itself into a  
>> composite controller or model of some sort.  Then there would be a  
>> standard but flexible way to hook that to the application's model.   
>> This would allow the app model to be whatever it needs to be for  
>> the app or the programmer's preferences, and just use a flexible  
>> but well defined interface for communicating with the rest of the  
>> system, which was all built automatically based on how the UI is  
>> put together.
>>
>>
>
> Yes, I have been trying to brainstorm something like this for one of  
> my projects. To me the most elegant solution is a model, view, and  
> controller which can each exist independently and don't need any of  
> the other parts.
>
> So you can have a View (wxPython app), say a contact list, that  
> allows you to add, edit, and remove entries. The View knows what  
> boxes to pop up, how to add entries to the View's list when you  
> click Add, etc. When "changes" occur (whatever ultimately requires  
> an updated Model), you just use pubsub like  
> pubsub.Publisher().sendMessage("CONTACT ADDED", ('Bob',  
> '755-555-1212', 'bob at aol.com')), or something like that. The View  
> doesn't care if anything is listening. The controller can pick up on  
> this, and make the appropriate model calls. Without a controller,  
> there is just no data persistence.
>
> When the View launches it would send a pubsub message, informing  
> anyone that may be listening that it can be populated with  
> information. Now if a controller is there, it could iterate over its  
> contacts, sending the identical messages ("CONTACT ADDED", ('Bob',  
> '755-555-1212', 'bob at aol.com')), and the View knows the appropriate  
> way to represent that contact.

No, if we're talking about MVC here, the view should not know how to  
represent a contact; the controller would store that logic. A view's  
sole purpose is to visualize data, and in order for the view to be as  
reusable as possible, it must know as little about the semantic  
meaning of that data as possible. A view should only know what type of  
data to draw (e.g. bool, string, number, custom) and where to draw it.  
In other words, a view should not know how to respond to a "CONTACT  
ADDED" message, because it should have no knowledge of the model, nor  
should it directly be passed data from the model like you suggest  
here. Instead, the "contact added" message should be sent from the  
model to the controller and the controller will do the work to add the  
contact to the view. (Or, the view will send a "Load data" message to  
the controller, and the controller will read through the model and  
populate the view with its data.)

The best way to think of the controller, IMHO, is to think of it as a  
translator. When something happens in the model, the controller  
translates it into terms the view can understand (e.g. a series of  
commands needed to visualize the change in the model), and when  
something happens in the view, the controller translates it into terms  
the model can understand (e.g. a series of data manipulations). I  
don't see the purpose of the controller sending out messages, as its  
entire purpose is to respond to messages from the model and view. From  
your comments, however, you seem to be visualizing the controller as  
just passing messages around, but really in that case, why can't the  
view just send messages directly to the model and vice-versa?

>
> You can also import the controller from a command-line and manually  
> call whatever functions the controller binds to the appropriate  
> pubsub messages (addContact(self, Name, Phone, Email)), (or you  
> could do it with pubsub :) without a need for the View.
>
> Using a solution like this and using pubsub, you can have multiple  
> Views for the same data and multiple Models storing the data in  
> completely different ways, without any extra work at all. You have  
> all these components just announcing occurrences, and anything that  
> wants to act on it can do so in the way it defines as useful.
>
> In less abstract words (from my blueprint at  https://blueprints.launchpad.net/wxbanker/+spec/proper-mvc) 
> : "Have the GUI and the controller send the same messages when the  
> same action is performed, with unique IDs created by the generator.  
> Each component maintains a list of uIDs to ignore, and a uID is  
> added to it either when it has already responded to it or has  
> generated it itself. For example, the user removes an account in the  
> GUI. The GUI sends ("ACCOUNT REMOVED", (uID, accountNum)). The  
> Controller receives this, realizes IT didn't generate the message  
> (based on the uID), and acts on it. It then sends the same message  
> (with the same ID). The GUI will ignore it, since it sent it and has  
> already done the appropriate GUI things. The Controller will also  
> ignore this message since it will have added the ID to its "sent"  
> list as well."
>
> So one way to accomplish better MVC in Python would to wrap pubsub  
> in a way which allows each component to send messages in a standard  
> way, and handling the aforementioned situations so each thing only  
> responds to the message once, and making this transparent to the user.
>
> Note all of this isn't strict MVC. To do it strictly (or as strict  
> as you can in wxPython) you would have to Bind all wxPython events  
> directly to the controller's appropriate functions. But this  
> requires a controller which not only knows details about the View,  
> but a View that REQUIRES an underlying controller. I don't see this  
> as being particularly elegant or useful.

A wxPython control/view will not require an underlying controller,  
unless you're using MVC, of course. ;-) If you do want to use MVC,  
though, yes, you absolutely need all three parts - a Model, a View,  
and a Controller. I personally think that calling Bind to bind view  
events to the controller for handling is not only useful but  
necessary. You do have to write that code somewhere - the only  
question is where. If it's not in your Controller class, then you're  
either tying your view to your model, or vice-versa, and making both  
less reusable with other controls because the controller parts will  
need re-written for each view.

AFAICT, your goal seems to be cutting all connections between the  
three components, but the reason we have the controller in the first  
place is because there needs to be something that links the model and  
the view together, and thus that must have knowledge of both of them.  
Now, you can merge the controller into the view (or the model) if you  
want, but the controller is still there (i.e. it's whatever code  
responds to "CONTACT ADDED"). The only difference is that you've now  
tied your view and model together, which IMHO is not a good thing if  
you want to reuse that code in another view.

Regards,

Kevin

>
> Okay, sorry for the long post, but I wanted to contribute my ideas  
> and ideally get some feedback as well.
>
> Thanks for reading, if you made it this far!
> - Mike Rooney
> _______________________________________________
> wxpython-dev mailing list
> wxpython-dev at lists.wxwidgets.org
> http://lists.wxwidgets.org/mailman/listinfo/wxpython-dev



More information about the wxpython-dev mailing list