Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Assume I have abstract base model class called MoneySource. And two realizations BankCard and CellularAccount. In MoneysSourceListViewController I want to display a list of them, but with ListItemView different for each MoneySource subclass.

What if I define a category on MoneySource

@interface MoneySource (ListItemView)
- (Class)listItemViewClass; 
@end

And then override it for each concrete sublcass of MoneySource, returning suitable view class.

@implementation CellularAccount (ListItemView)
- (Class)listItemViewClass
{
    return [BankCardListView class];
}
@end

@implementation BankCard (ListItemView)
- (Class)listItemViewClass
{
    return [CellularAccountListView class];
}
@end

@implementation MoneySourceListController
- (ListItemView *)listItemViewForMoneySourceAtIndex:(int)index
{
    MoneySource *moneySource = [items objectAtIndex:index];
    Class viewClass = [moneySource listItemViewClass];
    ListItemView *view = [[viewClass alloc] init];
    [view setupWithMoneySource:moneySource];
    return [view autoreleased];
}
@end

so I can ask model object about its view, not violating MVC principles, and avoiding class introspection or if constructions.

Thank you!

share|improve this question

2 Answers 2

Have a read of Martin Fowler's article on MVC.

The short synopsis is that your structure is wrong. From the 4th paragraph discussing MVC: Model objects are completely ignorant of the UI. And in your question, you're discussing how the Model can return different types of Views.

That you're having the model return the view is probably the first thing that I would fix. The Controller could / should have the logic that modifies what the View displays based upon which Model is being used.

Edit

Still wrong*, sorry.
*wrong == not following MVC or its variants.

The Model is nothing more (and nothing less) than the method to access the data.
The Model and the View should have no idea of each other, and having the Model return a View type violates this principle.

The core issue here is that your logic for object instantiation is at the wrong place. The Controller, not the Model, is the appropriate place for this logic. Your use of categories is orthogonal (ie. unrelated) to this design issue.

To be a little bit more concrete, I'm going to simplify the example and assume that the MoneySourceListController is told what type of account is in play. Another View & Controller could pass that information along or it could be derived from a Customer object that's part of the domain. For that matter, it could be another area of the MSLController and some static portion of the View.

Once the MSLController knows what type of an account is required, it needs to do two things.

  1. Create the associated View based upon the logic in MSLController regarding account types.
  2. Create the associated Model class, again based upon the logic in MSLController regarding account types.

The Controller is the traffic cop that determines which View(s) and which Models get created. I would have to go back an re-read all of Fowler's article to determine if there is a strict 1:1 ratio between Controller and View or if a Controller can have multiple Views. It's a nuance of MVC vs. MVP vs. MVVM that I don't pay too much attention to. I asked a related question for MVVM.

From your point of view, I'm assuming you're trying to use MVC to increase your ability to scale and maintain your app. Having the Controller create the Model(s) and View(s) as I outlined above will give you those benefits.

share|improve this answer
    
I agree with you. But this category is the part of Controller implementation. Original model class is still aware of View. So if I need to change view for model I don't change Model class, i just change category. –  Denis Mikhaylov Sep 18 '12 at 13:58
1  
Either you are not asking your question correctly or @GlenH7 is correct. Your model shouldn't be returning anything dependent on a view. The controller should be handling what the view needs. If the view, model, and controller are tightly coupled enough that the model needs to know about the view then there is an issue. –  Rig Sep 18 '12 at 14:23
    
@DenisMikhaylov - Rig is spot-on, and based upon my understanding of your question I do not believe you are following the MVC pattern. That having been said, you don't have to follow the pattern if you don't want to. What you've asked about / described doesn't match the MVC pattern because the Model and the View shouldn't know of each other. If MoneySource is your Controller, then please edit your question and stop calling it the Model. –  GlenH7 Sep 18 '12 at 14:44
    
@GlenH7 Do you know what is category in objective-c? –  Denis Mikhaylov Sep 18 '12 at 15:19
    
@DenisMikhaylov - I didn't until I just googled it. And I'm still not clear on the terminology for MVC that you're using. When I capitalize Model, for instance, I am specifically referring to an object that acts as the Model in MVC not some generic term "model." If your current structure is MoneySource as your Model and CellularAccount | BankCard as your Controllers because they've extended the Model via categories, then I think you still have a categorically bad design that does not follow MVC. The extension leaves the Controller with functionality from the Model that it should not have. –  GlenH7 Sep 18 '12 at 16:12

I think you are skipping the concept of viewmodel or mixing up that with model.

It is correct to say that your controller should have define which view should be displayed. However, ideally each view should have their dedicated viewmodel for specific scenarios like: when your model is big or view needs some other information - which has all minimal set of data elements that your view is supposed to render.

Basically, your viewmodel may consist from a single model or multiple-models. However, it should have only minimal set of data elements that your view requires.

In addition, you may manage your role access security through your view-models as well.

share|improve this answer
    
ElYusubov, he's using MVC, not MVVM. He specifically mentions using Objective-C as a tag, and AFAIK, Obj-C doesn't support binding from the View. The primary difference between MVVM and MVC is that MVVM uses binding between the View and View-Model. As the question is currently written, I agree with you that he's skipping the Controller (aka VM in MVVM). –  GlenH7 Sep 18 '12 at 15:07
    
GlenH7, my comments actually targeted MVC design pattern. In MVC project, we had instances where a separate viewmodel for each views were build to increase productivity. Binding models(the data/entites) to views may have shortcomings. But it is another topic. –  Yusubov Sep 18 '12 at 15:29

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.