Using the MVC pattern in a desktop application, what's a good approach to introducing a view to its respective controller, and vice-versa? E.g., should you use constructor injection to give the view its controller, then have the view call a setView method on the controller and pass itself as the argument?
(Question isn't specific to any framework/platform.)
Views should be as dumb as possible. They shouldn't know about, or rely on having specific controllers instantiate them. At best they should have access to some kind of base controller class reference that is handed to them upon construction, usually as part of the "view data" object which wraps the Model to be used as well.
Your controller should be responsible for instantiating the view, giving the view the model it will be displaying, and returning the view's result. The view shouldn't be calling back into the controller to tell it what to return, as this gives control of the logical flow to the View, which isn't really MVC-like.
Related
Part of Apples description of the MVC-pattern is: ”The controller updates the model.” I interpret this to simply mean: The controller calls methods on the model, causing its internal state to change.
But for a controller object to call a method on a model object, it needs a reference to the model object. If multiple controllers need to update a model object, we need multiple references to the model object – one for each controller.
I don’t want my controllers to reach out in to global space locating other objects. I want higher level application objects to wire up lower level domain objects.
I’m coming from other plattforms where we use IOC containers for this stuff.
Looking for best practices as how model objects gets passed around in a cocoa application.
A concrete example: If I add CoreData to the cocoa application project template in xCode, the managedObjectContext is instantiated in the app delegate. How do I pass this instance to, for instance, a view controller or a nested view controller?
I’m using Swift.
concrete example: If I add CoreData to the cocoa application project template in xCode, the managedObjectContext is instantiated in the app delegate. How do I pass this instance to, for instance, a view controller or a nested view controller?
So personally I find this an anti-pattern: stuffing 'global' data in the app delegate.
But, that is what is very common on iOS and as you have noticed, what the standard Xcode template does. Unfortunately.
To make this a bit more workable, what I usually do is make the managedObjectContext private to the app delegate. Then when another object, mostly a UIViewController, needs to access this context, I explicitly pass it to the UIViewController when I instantiate it.
And when that view controller needs to display a new view controller, like for example some detail view, I again pass the context to it.
Then at least there a clearer form of responsibility. And it makes testing simpler because view controllers simply need to be configured (or injected in IoC terms) instead of grabbing hard coded global objects.
I know this not a full answer to what you were asking but I thought this bit was the most interesting of your question.
In the classic MVC:
The setup mechanism is the following:
Instantiate model
Instantiate view (Has reference to a controller, initially null)
Instantiate controller with references to both (Controller registers with view, so view now has a (non-null) reference to controller)
The question is why in the second step the view should have reference to the controller (i think the controller having a reference to the view is enough) ?
In the Extended MVC:
The setup mechanism is the following:
Instantiate model (Has reference to view, initially null)
Instantiate view with reference to model (View registers with model)
Instantiate controller with references to both (Controller registers with view)
The question is why in the the first step the model should have a reference to the view (what i know is that the model shouldn't know anything about the views, and the pattern Observer should be used in this case) ?
Here is the source link.
Thanks for advance.
The answer for both questions is the same. Your diagram is very abstract and you are totally right there should be no direct reference in both cases. You can either reference by a well defined interface(duck typing) or by subscribing to events happing at the observable object.
Look at your observer example. According to it, the only thing an observable knows about its observer is the fact that they respond to the notify method. So technically there is actually a circular reference between the two, but in case of the reference from the observable(model) to the observer(view), it's a week one.
Same applies for the first case. The View does not directly know the controller. But the controller has to be notified on UI events(e.g button clicked) and respond to them. This is often done by having the controller register to events happening in the view. But technically the view will maintain a list of its event responders. So there is actually a reference, but again a weak one. It will not stop you from reusing the same view with another controller.
So, your concerns are right, circular dependencies are a smell. But on the low technical level they are required and in order to achieve lose coupling you just have to make one side of them weak, which will make the dependency exchangeable
I was going through the articles describing the MVC pattern. None of them were clear on explaining the role of Controller in MVC. Some says Controller can make changes to the view such as disabling a button or changing the text color whereas some says any changes to the view should be done inside view only. Can you please give me tips on the following question?
1) Can any change pertaining to the view be done inside the controller?
2) What not should be written inside a controller?
3) It is right to say "View should do all the changes by itself when a new recordset is generated by the model, as the view queries model directly, and controller is not involved in this transaction?"
4) I have heard this statement about MVC "In current version of windows application development. View is capable to handle the event(like button press) and the controller is called when needed.It is stupid to delegate the event listening to the controller now." Doesn't this sound more like a MVP?
Thanks. Hoping to get some help here.
In my opinion:
1) The controller changes the data provided to the view, so in a way, yes. The view should just manage the presentation of the data provided to it by the controller.
2) The controller should contain all code to handle any actions taken by the user. Depending on the size of your application, the controller can hand the action off to a business layer to do the work then gather view data once the business layer is complete and hand it back to the view. Or, if you don't have a business layer, it can do the work directly.
3) In true MVC, the view should not have access to the model directly. The controller should create view objects from the model and pass them to the view. In any case, the view should never do any real work other than presentation.
4) I don't know MVP so cannot answer this question.
1) Controller responsibility is primarily "execute an action, choose an appropriate view, provide some data to that view and return the view to a user".
2) As MVC tries to separate presentation logic and UI rendering, I believe, controller shouldn't attempt to perform any of view responsibilities: listening to UI events or pre-formatting of values dateString = data.ToString('YYYY-MM') - that's all should go to view.
3) in MVC view knows all about a model - model is rendered by view without any controller involvement (that's primary 'issue' fixed by MVP, where view should and model should unbound as much as possible). However it's not recommended for view to query model directly. Instead, all data changes should be reported to view by model using Observer pattern.
Consider the following -
schema from wikipedia article - dashed line from model to view indicates that fact. Just keep in mind that model is more viewmodel here and shouldn't really be a part of BL layer.
So here scenario could be the following:
User clicks "add item"
View sends request to the controller with the item data
Controller makes call to BL, which makes changes to the model (adds new item to the list).
Model fires "updated" event to the view (or "error" event, if there are some issues in underlying layers)
View updates UI according to changes reported.
4) The statement is perfectly true. In MVC you shouldn't do that. I assume, in MVP you shouldn't do that as well - I mean, listening to events from UI directly. That should be done either by forwarding event by view; or using a platform-independent view representation, like
inderface IMyGridView
{
event ItemEvent AddItemClick;
}
(which doesn't make sense for MVC, as view is pretty much independent from a controller and mostly all view actions are result in calls to controller).
I'm a bit confused about mvc terminology.
Using the question title as an example, a view corresponds to an action, which means xxTemplateFile would be considered to represent the view.
xxFolder does not represent an area. So could it be a View Collection? or View Container?
Cheers,
This could reprisent the controller class and controller method for the related view. (or controller and action with the view being attached to the action).
Using your example: Views/XXFolder/xxTemplateFile could be used to indicate that your view, xxTemplateFile which is attached to a controller action of the same name, is inside the xxFolder class.
This would make sense if you consider how routed URLs tend to look {controller,action,id}
If this is simply the way you're organising your views then I'd be tempted to just refer to them as View folders or folders.
I have a object that is responsible for controlling screen navigation. A presenter can call one of two methods on this navigator object NavigateTo(string screenName) and NavigateTo(string screenName, object data). This latter method allows some context data to be passed to the navigator object.
Would it be the wrong approach when calling the NavigateTo(string screenName, object data) to pass the calling presenter as the data to the navigator and then allow the navigator object to use this to extract data from the view and/or model.
Some advice on this matter would be greatly appreciated.
Passing the Presenter to NavigateTo is a good choice. If you have multiple presenters you may want to write a interface that NavigateTo can use and have each presenter implement that interface. But if you just using one presenter for this or they already share some common interface then this is not needed.
One idea behind MVP is that you are change the view without effecting the underlying UI Logic. Passing the presenter doesn't effect this goal of MVP as you can change the view the Presenter is using. Now if you are allowing direct access to the raw view through the presenter (by exposing a view property) then that not good. What you want are methods on the presenter to expose the needed information to NavigateTo. That way when you chance the view you re implement the code behind those methods.