6

As a beginner in programming it always bugs me when I run into a walls. Currently one of the wall are co-depending objects.

As you can see in my question history I'm currently working on a blackberry application, in which I implemented something I call the MVC Pattern, but it isn't exactly what I think it's meant to be.

You see, a novice programmer you look on abstracts like this graphic and you get the idea behind it. But implementing it is another thing.

alt text http://www.ibm.com/developerworks/wireless/library/wi-arch6/theoretical.gif

Please, don't stop reading :) I'm showing you some of me code, which contains some blackberry specific stuff, but you should see what I'm doing.

Main Entry Point for my Application

public class ContactManager extends UiApplication
{
    private static ContactManagerMainScreenModel MainScreenModel = new ContactManagerMainScreenModel();
    private static ContactManagerMainScreen MainScreenView = null;

    public static void main(String[] args)
    {
        new ContactManager().enterEventDispatcher();
    }
    public ContactManager()
    {   
        MainScreenView = new ContactManagerMainScreen(MainScreenModel);
        // Displays the Splashscreen then opens the Mainscreen 
        new SplashScreen(UiApplication.getUiApplication(), MainScreenView);
    }
}

The Mainscreen Model

public class ContactManagerMainScreenModel
{
    ContactManagerMainScreen v;
    // Loading Local Storage
    LocalContactStorage LocalContactStorage = new LocalContactStorage();

    // Define Data List
    private Vector vContacts_Favorites;

    public void register(ContactManagerMainScreen v)
    {
        this.v = v;
    }
    // Retrieve Favorite Contacts from Persistant Storage
    public Vector getFavoriteContactsFromLocalStorage()
    {
        vContacts_Favorites = LocalContactStorage.getFavoriteContactsFromLocalStorage();
        return vContacts_Favorites;
    }
    // Put Retrieve Favorite Contacts from Persistant Storage
    public void saveFavoriteContactsToLocalStorage()
    {
        LocalContactStorage.saveFavoriteContactsToLocalStorage(vContacts_Favorites);
    }
}

The MainScreenController

public class ContactManagerMainScreenController 
{
    private ContactManagerMainScreenModel _model = null;
    private ContactManagerMainScreen _view = null;

    public ContactManagerMainScreenController(ContactManagerMainScreen view, ContactManagerMainScreenModel model)
    {
        this._model = model;
        this._view = view;
    }

    public void HideFavoriteList()
    {
        if( this._view._ContactList.getManager() != null)
        {
            this._view._ContactList.getManager().delete(this._view._ContactList);
        } else
        {
            this._view._bottom_box.add(this._view._ContactList);
        }
    }
}

Still there? Okay ...

My Problem here is, that I want to use the controller to change UI Elements, like Displaying a PopUp Box, hide someting or other things.

But all these UI Elements are defined in the View (here ContactManagerMainScreen) so have to give to the Controller a reference to the View. Which leads to my co-depending objects misery.

I cannot create the controller before the view is declared. Without the requirement to allow the controller to change UIElements, it would be no problem (as shown in the Graphics).

What I'm doing now is that the View creates the Controller

controller = new ContactManagerMainScreenController(this , model);

Does that makes sense? I want to understand the pattern, so call my code trash or anything you like :) I just want to learn something.

P.S. I beg your pardon for my bad english :)

Henrik P. Hessel
  • 36,243
  • 17
  • 80
  • 100

4 Answers4

11

MVC is an interesting abstraction, but has some problems.

In reality, the controller and view are often paired--even though in theory you should be able to replace either one without the other, in reality the interface mechanisms to different views are so different that the controller & view are combined.

The best description I've seen relating to Java is that the view is your swing components so your portion of the view code is nothing but placing those components on the screen.

Your controller is the rest of that class, the listeners and the rest of your code that interacts with the view.

My suggestion would be to not worry too much about isolating the view and controller, but that said, I am totally behind keeping a very strong separation between the model and the view/controller.

EDIT/Advanced: I have used a pattern where controller and view are isolated and it is more flexible, but it tends to be a lot more work. I think Struts uses the binding model--if you want to see some abstraction techniques you might look there or search for stuff about "binding" swing controls.

Bill K
  • 62,186
  • 18
  • 105
  • 157
  • (Though if anyone *can* make a case for how to sanely separate the view and the controller, I would be very interested.) – Zarkonnen Jul 13 '09 at 16:11
  • Thanks for your answer Bill. One of my fear is, as you realized, is "Writing bad code". Do think my implementation is acceptable? One more thing: " [...] that the view is your swing components and your view code is nothing but placing those components on the screen. [...]" Did you meant " [...] your controller code is nothing [...]"? – Henrik P. Hessel Jul 13 '09 at 16:13
  • It is possible to separate the view and the controller, but IMHO not as clean as can be achieved in a web application. – Praveen Angyan Jul 13 '09 at 16:16
  • Yeah, I used the word model a few times when I was thinking controller. Thought I caught them all on review. Also your code looks fine--I've seen much worse. If you had to develop 50 screens with dozens of controls on each I'd say seriously look into creating a system that uses binding, but for just a couple screens, the traditional techniques work fine. – Bill K Jul 13 '09 at 16:19
  • @Praveen Not really, on a web app, your "View" is "The Web". If you switch that out to another view (say swing controls, or a database front-end or a CLI, I bet you are going to replace most of your controller code as well). MVC only seems easier on the web because you assume you are never switching views. – Bill K Jul 13 '09 at 16:22
  • @Zarkonnen - Sure, have a Controller thread that monitors an Event Queue. Both the Models and the View place things onto this queue whenever they have an action. As items are popped off of the queue certain actions are performed by the controller, and messages are sent to either the view or model (depending on the message). – amischiefr Jul 13 '09 at 16:33
  • @Zarkonnen - Consider a table view. The controller contains a list of model objects, and the controller implements a "TableDataSource" interface that the table view defines. The table view isn't tied to the controller, it's tied to TableDataSource. That creates a fair amount of separation by using dependency injection. – Tom Dalling Jul 15 '09 at 09:01
3

I don't think that diagram is very good, and probably makes things a lot more confusing.

The controller should be responsible for giving the Model to the View. The Model should contain nothing more than simple accessors for your data. Any need to interact with the Model - or change any of it's values - should take place thru the Controller.

This way, the View only needs to know how to render/present the Model to the user. So any operations on the Model - things like saveFavoriteContactsToLocalStorage() - should be methods of the Controller, not the View class. Also, the Controller should not need a reference to the View to be constructed - I think that ends up reversing the intended order of the entire MVC pattern.

matt b
  • 138,234
  • 66
  • 282
  • 345
  • I believe his diagram is correct. The problem is that MVC isn't a good abstraction and every toolkit tweaks it in such a way as to make it fit the way they designed it. Some do a good job, some not so good--the one thing that is for sure is that if you change the view, you're going to end up changing the controller (which is against the theory). – Bill K Jul 13 '09 at 16:26
  • Perhaps. I'm only really familar with using MVC in web contexts, in which case the Controller would simply return the View and Model to use (as in Spring MVC). I suppose it might be quite different on the desktop. – matt b Jul 13 '09 at 16:31
2

I agree with Bill K. Standard MVC is not that important when dealing with rich client. It is a great model when writting web apps as events (clicks in your browser) are quite different than your view (HTML render).

With standard GUI, a better model is something called PAC (presentation/abstraction/Control). Here the presentation is (the view + the event handler), the controller manage the exchanges between the presentation and the abstraction. And the abstraction is your business model.

This way you have a controller that manage the link between the GUI part (view + user events) and your abstraction. You have a PAC agent for any piece of GUI you develop and a clean separation between them.

Another article about something better than MVC related to PAC : HMVC. Quite old, but it is practical and it helps understanding things.

neuro
  • 14,948
  • 3
  • 36
  • 59
1

From my perspective, this is something I ran into when I first tried to separate out my Models, Views and Controllers in my first desktop application.

With Web Applications, the MVC pattern fits VERY naturally because of the innate nature of the web, but unfortunately it's not possible to fit a pure MVC patter to a desktop app, where the Operating system plays an innate role in notifications. This usually leads to the pattern being implemented as you've shown in your diagram.

However the pattern that you've shown really needs to be implemented like this, I think (I've switched over to .NET after a brief affair with Java, so please keep that in mind):

public class ContactManagerMainScreenModel
{
    ContactManagerMainScreen v;
    // Loading Local Storage
    LocalContactStorage LocalContactStorage = new LocalContactStorage();
    // Favorite list
    boolean showFavoritesList = true;

    public void register(ContactManagerMainScreen v)
    {
        this.v = v;
    }

    public void ShowOrHideFavoritesList()
    {
        if(showFavoritesList) 
        {
            showFavoritesList = false;
            v.RefreshView(this);
        }
        else
        {
            showFavoritesList = true;
            v.RefreshView(this);
        }
    }
}

Meanwhile the controller would be responsible for receiving user actions. So if you have a button that says "Toggle Favorites", this would cause the controller to call _model.ShowOrHideFavoritesList(). The model would update itself and ask the view to refresh itself using it's new state.

The view would now be free from the dependency on the controller.

Praveen Angyan
  • 7,227
  • 29
  • 34
  • Again, thanks for your answer. Your implementation would lead to a model which directly controls the UI itself. Would you suggest dropping the entire controller? – Henrik P. Hessel Jul 13 '09 at 16:16
  • No, please read my last two paragraphs after the code. The controller is responsible for handling ALL user notifications. Here's another example. Let's say the user clicks on "Add New Contact", the controller would be responsible for calling _model.AddNewContact(string firstName, string lastName). The model would then add this contact to it's own internal state and then call RefreshView(this) on the view. – Praveen Angyan Jul 13 '09 at 16:21
  • What I mean is that the controller is still responsible for capturing all user notifications and then decidiing how to update the model. The model then always calls RefreshView(this) on the view which then redisplays itself... – Praveen Angyan Jul 13 '09 at 16:21