Hi Kevin,
Kevin Ollivier wrote:
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.)
Yes, I think you have some valid criticisms of my concepts. Maybe what I want is not MVC, but I don't like the idea of requiring a Controller for the View to be useful, and then coupling the Controller to that View. If you bind the events directly to the controller and then manipulate the wx objects from the controller (which I have done in one project), that becomes very awkward to me. Now if you want another sort of View, say Excel, HTML, text, et cetera, your Controller can't handle it. You have to make some meta-Controller which handles all of the controllers for each View, and has to know exactly how many Views and Controllers there are and are active at any given time. Manipulating Excel tables is only useful for an Excel View, why abstract non-abstract knowledge? You are just moving it for the sake of moving it.
I guess I just don't understand the point of taking logic out of the View which only pertains to the View. I would like Views which understand how to display the appropriate raw data, which the controller handles/generates, and the model stores.
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.
In many ways your description seems to match what I imagine as well. However I don't understand the criticism of the Controller sending messages. This is only barely different from the Controller calling View functions, which your concept does. This is exactly what sending the messages accomplishes anyway, except now it has been wrapped in such a way as to make the Controller agnostic to the *specific* View (not Views in general!) and how many of them there are, if any. The entire purpose of the Controller is not to respond to messages from the Controller and View, it is to actually DO things (the business logic), and then let the View and Model know when to update themselves. It doesn't need to know the nitty-gritty implementation-specific details of doing so.
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?
No, the Controller handles all the business logic. It knows what needs to be persisted and when; neither the View or the Model care about or understand this. It understands what actions are valid and when. With my idea of MVC, you can import the controller, and call all the methods you want to create and manage files in whatever is appropriate. This allows the application to be used from a command-prompt, PyShell, et cetera. If you have a View, you also get to see those changes happening (and perhaps interact with them there), and if you have a Model, those changes get persisted somewhere. But you shouldn't NEED either of these to perform business logic.
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.
The controller does do this linking you say and has knowledge of both of them, just not SPECIFIC knowledge. It knows a View may be out there presenting data and allowing the user to manipulate it, and it knows there are ways to represent this data in a persistable way via a Model. It knows what sorts of things a View may be interested in, and what sorts of events and actions the Model may be interested in, and handles all the logic in between.
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.
But you are only saying I have tied the the Controller and View together because you are calling something a Controller which I am not, and mixing our views. It is perfectly fine to criticize why my View does too much or why my Controller does too little, but you can't say my Controller is coupled to the View and be consistent with either of our ideas. What you are really saying is YOUR idea of a Controller is coupled to MY idea of a View, by calling my idea of a View a Controller from your point of view. This mixing and matching doesn't make sense from either of our conceptions of MVC.
Anyway, thanks for the response, you definitely have some valid criticisms which I appreciate and I will have to think more about the proper way to do things. I have to figure out how to not couple business logic with my View while not depending on a Controller to function. I think this would be possible by removing the conditional logic from the View and instead allowing a Controller to 'veto' any actions which are not allowed. I agree that a strict MVC approach where you bind the events to the controller can be an elegant approach, granted you only want to work with one sort of wx View. It did clean up our code a lot and made it easy to work with, but later when we wanted to take our business logic elsewhere for another application, it was too coupled to a specific View.
I would just really like a nice way to have a portable business logic module (what I am calling a Controller), and then be able to (optionally) link Views to one side of it and Models to the other, and as long as they conform to the API, it all just works and the Controller ensures that the data flows as it should when it should and how it should.
Thanks again,
Mike