MVC paradigm: exposing model and controller from view - model-view-controller

I find myself needing to have a View expose its Model and Controller references. Is this the smell of bad design? Or is this considered "safe" practice?
For example: I have a list (composed of a ListView, ListController, and ListModel) and many list items (composed of a ItemView, ItemController, and ItemModel).
When I create the ItemModel, ItemView, and ItemController for each list item, I pass the ItemView instance off to the ListView. But, at some later point, my ListController needs a reference to the corresponding ItemController instance.
So, would it be more proper to pass both the ItemView and the ItemController in to ListView::addItem(), or just pass in ItemView and expose an instance method such as ItemView::getController()?
Or doesn't it matter? Is each approach equally viable? If followed to their logical conclusion, does either tactic result in an anti-pattern?

But, at some later point, my ListController needs a reference to the corresponding ItemController instance
Why? If you're decoupling your classes properly, you shouldn't need this.
Controllers almost always address a functional domain. An example of such a domain might be "Sales" or "Admin." In addition, MVC also supports the use of "Areas," which provides an additional hierarchical level of organization.
Adding references to controllers from other controllers is at cross-purposes with this organizational structure. If you need to combine functionality to make your code more DRY, ordinary refactoring will accomplish that. You can also inherit controllers from a base class containing common functionality.

In the mvc pattern the users request shall be routed to a controller, say invoicecontroller, that has actions.
Lets say the default action, Index, returns a list of invoices; the controller then creates a model with a list of invoice objects, instantiates the correct view and injects the model into the view.
Now it is the views turn to do its magic. It renders the best view it can with the data it has, which may include routes to one or more controllers.
In NO instance should the view (or model) do business logic themselves.
That said, I totally agree with Jakub. Hope that helps.

Considering you are not actually showing any code at all.
In my opinion, you should change your design. A controller is not supposed to communicate with another controller (directly), MVC dictates it: reference.
If you need to invoke a controller action from another controller, consider using delegates or composition. Instead of directly invoking the controller action.

Related

MVC, controller - use cases

I've learned that you should set up the controller-class in a MVC-OOD as a use case, from top to bottom in only one method that run the MVC-classes.
Is it OK to use different methods in one controller to get more control and better overview?
Let's say you wanna run a controller that will display a login form (getting the html etc from the View). And the same controller will also display a log-out button IF the user is NOT logged in.
This could be done with a single method in the controller, but using two methods seems better. One method to call if you want the login form, and one to call if you want to log-out button.
(just an example)
So, what does the pros say. Should each controller contain one "use case" method only, or could it be several?
TL;DR -- you have misunderstood the MVC design pattern and are doing it wrong.
Controllers are not responsible for rendering the interface, nor for presentation logic. Controllers do not display anything. Instead, each controller's method deals with different user's request. It extracts the data from said request and passes it to model layer and the associated view.
Decisions about what and how to display are in purview of views. Views contain the presentation logic in MVC pattern. In the context of web applications, views create the response. They can compose a from from multiple templates or just send a single HTTP header.
Controllers can signal the associated view by passing some specific values of the request to that view, but most of the decisions in the view are based on information that the view requested from different services in the model layer.
A Controller's methods are based on what type of requests a user can send. For example in a authentication form it might be: GET /login and/or POST /login.
Its important to remember two things with MVC, firstly, its an Object-Oriented Architecture, and secondly, It should be used for separating concerns.
Separation of Concerns is related to Abstraction, It is to aid us in understanding the section of code at hand. The Model and View are both collections/domains of related objects. Each object is fully complete and relevant to its domain.
You will find objects with types such as Buttons, Images, Text Inputs etc inside your View, and you will find business related objects (User, Account, Profile etc) within your Model.
The collection of objects inside your Model don't tend to do much, They require logic to wire the objects together. (Or simply delegate simple single object requests to the correct object)
The Controller provides the interface into your Model, and contains the business logic related to the Model and the interactions between the Model objects. You will have a single Controller for your Model, and the Controller will have multiple methods which will align with your use-cases.

Would you create a View Model if it was the same as other pages?

Thanks to previous answers, I have now written View Models and really like this concept, however, there are points in the application where the View Model will be the exact same as the (Not sure on the term..) real model.
Now in this situation, I understand that a View Model is best as one day, I may change the application logic, and it makes the application more robust.
However, a situation I have now is where I have a multiple pages that are very closely linked to each other and all need the exact same Model. In this situation, would you use the same View Model or just create a separate identical one for each page?
Are they exactly the same? In my opinion, if they are exactly the same you should reuse the ViewModel. Why create the same ViewModels twice whose functionality is basically the same. However, you should be careful that there are no service calls being in ViewModel constructor because, you may not need the exact same service calls for all views. In that case your calls are wasted even though you do not require it. In such a case make a public method in ViewModel like :
public void DoServiceCallsForViewA()
{
ModelObj.FooA();
}
public void DoServiceCallsForViewB()
{
//your calls for view B
ModelObj.FooB();
}
Then in your viewA you can typecast the DataContext,
((YourViewModelName)DataContext).DoServiceCallsForViewA();
and in your viewB you can write :
((YourViewModelName)DataContext).DoServiceCallsForViewB();
ViewModels should be simple data vehicles between views and controller actions (just a list of properties). If they are simple lists of properties in your app you can use Automapper to make your eventual decision on this fine detail less important.
...not to evade the question, I would stick with one ViewModel definition while the views are demanding exactly the same data shuttle and be ready to create a new ViewModel when one of those views needs something ever so slightly different.
There is no need to duplicate except to make your view:action mappings obvious, but weighing the obvious mapping against violation of the DRY principle seems like a straightforward decision...
The way I see it, your Model instances should each have an associated ViewModel. That is to say, you should have a 1:1 relationship betweel Models and ViewModels. You are however free to bind multiple Views to the same ViewModel.
Say, for example, you have a Person object, and a PersonViewModel, and then two different Views relating to that Person, say a PersonEditView and a PersonDetailsView. You should put all the neccessary properties for both PersonEditView and PersonDetailsView into PersonViewModel. Then use a DataTemplateSelector to choose which View should be displayed for the ViewModel at which times.
The each ViewModel instance should be a representative for a single Model instance, and it should be the only representative for that Model instance.

How to implement polymorphism in sproutcore?

I am developing an application that involves a type hierarchy and started by defining the models for each type via inheritance. When it comes to writing the corresponding controllers I am not sure how to approach the whole thing in a clean way. Should I write only one controller for the base type that is able to handle derived models or should there be one controller for each subtype? How should the view-controller bindings be set up to work with the different controllers?
You might want to check out SproutCore's new experimental polymorphism support: http://groups.google.com/group/sproutcore-dev/browse_thread/thread/b63483ab66333d15
Here's some information on defining sub-classes and overriding properties and methods:
http://wiki.sproutcore.com/w/page/12412971/Runtime-Objects.
From my (limited) use of Sproutcore, I've only been able to bind 1 view to 1 controller.
As such, if you are planning to use a single view (e.g. ListView) to display your data, then I think you will only be able to bind that view to 1 controller. This means the 1 base type that is able to handle derived models seems to be the way to go.
Typically you populate the content of ArrayController instances with the results of App.store.find calls. SC.Store#find can take an SC.Query instance, which typically looks like:
MyApp.myController.set('content') = MyApp.store.find(SC.Query.local(MyApp.MyModel));
This should return all instances of MyApp.MyModel, including any instances of MyApp.MyModel's subclasses.
The first argument to SC.Query.local can either be an SC.Record subclass or a string referring to the subclass. So if you've got some intermediary SC.Record subclasses, you might want to try using them there.
Controllers should just be proxies for objects, when dealing with single instances of your model. In other words, ObjectController can proxy anything. Here is what I mean in code:
You have two objects, Person and Student.
App.Person = SC.Object.extend({
// person stuff here
})
App.Student = App.Person.extend({
// student stuff here, you have have all Person things because you are extending person.
})
You then want to define controllers:
App.personController = SC.ObjectController.create({
contentBinding: 'App.path.to.person'
})
App.studentController = SC.ObjectController.create({
contentBinding: 'App.path.to.student'
})
note that you would only bind the controller's content to something if the person/student is a result of a selection, or some other flow where bindings fire. In other words, if you set the person manually (say from a statechart, as the result of an interaction), you would still define the controller but would do
App.personController.set('content', person);
You set up the controller differently depending on whether the Person is a 'top level' object in your app, or some intermediate object that gets selected. Also, you might only need one controller, you would only have a studentController and a personController if you were acting on a person and a student at the same time. Both are just ObjectControllers, and those can proxy anything.
Finally, in your view you would bind the relevant view element to the controller:
...
nameView: SC.LabelView.design({
layout: {/* props */},
valueBinding: SC.Binding.oneWay('App.personController.name')
})
...
note that the oneway binding is if the name is not going to be changed on the view, if the view can change the name, then just do a normal binding. Also note the path here. I am not binding to
'App.personController.content.name'
Since the personController proxies the object, you bind to the
'namespace.controller.property-on-object-controller-proxies'
If you are putting a lot of business logic in your controller, you are doing it wrong. Controllers should just be for proxying objects (at least ObjectControllers should be). Business logic should be on the models themselves, and decision making logic should be in statecharts.

MVC, how view should be accessed from controller?

I'm just learning MVC so you could find my question rather strange...
My Controller have access to different shared objects through Container object passed to Controller's constructor. To access shared objects I should do $this->container->db to access Database adapter or $this->container->memcache to access Memcached adapter. I want to know should I put View object into Container with shared objects or no?
From one side it is really comfortable to take view from this container, but this way I couldn't create multiple Views instances (for example, every time I'm calling Controller's method from View I should have one more View instance). What is the solution? How should I pass View object into Controller and/or how should I create new View instances from Controller?
Thank you!
If you want that DI experience, do it on views as well, but I don't know if it really helps you anyway. Never call controller methods from views. Instead write some partial view methods and call them from views, which define the page layout (something similar to what Rails does).
IMHO if you want to get on MVC gradually, start from core principles and iteratively get to details, but don't learn architectural/design pattern as MVC by parts - architecture, design, the whole matters:)
Hmm, maybe try implementing caching for static parts. IMHO try inserting cacher object (through DI) to controller, and let that object decide if you want to send cached partial view or instantiate a new one. If you want to cache data from db, use the same pattern from controller towards models, so whenever in a controller you need models, ask db cacher object (same DI principle). Is it clear enough?

MVC - Calling Controller Methods

My application is following the MVC design pattern. The problem I keep running into is needing to call methods inside a Controller class from outside that Controller class (ex. A View class wants to call a Controller method, or a Manager class wants to call a Controller method). Is calling Controller methods in this way allowed in MVC? If it's allowed, what's the proper way to do it?
According to the version of MVC that I am following (there seems to be so many different versions out there), the View knows of the Model, and the Controller knows of the View. Doing it this way, I can't access the controller. Here's the best site I've found and the one describing the version of MVC I'm following: http://leepoint.net/notes-java/GUI/structure/40mvc.html. The Main Program code block really shows how this works.
Thanks for any answers.
Take a closer look at this paragraph from the article you linked to:
View
This View doesn't know about the Controller, except that it provides methods for registering a Controller's listeners. Other organizations are possible (eg, the Controller's listeners are non-private variables that can be referenced by the View, the View calls the Controller to get listeners, the View calls methods in the Controller to process actions, ...).
You have the observer pattern here between the View and the Controller. MVC is not a single pattern per se but at least two combined.
One way to get your head around managing the View/Controller communication is to use events. The View fires events on certain user actions (without knowing necessarily who might handle them.) The Controller processes these events and acts accordingly.

Resources