PDA

View Full Version : Model-View-Controller design pattern



Rezmason
August 10th, 2007, 10:43 AM
I just picked up Advanced ActionScript 3 with Design Patterns (http://www.amazon.com/Advanced-ActionScript-3-Design-Patterns/dp/0321426568), and I'm very interested in the Model-View-Controller pattern (http://java.sun.com/blueprints/patterns/MVC-detailed.html). If any of you know what that is, I'd like to talk with you folks about it.

In my latest project I have inadvertently applied the MVC design pattern. My Model class has getters that return data to the caller (which is most often one of my View classes' methods) after validating and formatting it. People who document the MVC pattern typically assume that the data being passed in this way is of some kind of basic type, and that the getter is called infrequently. In my case, the Model class passes BitmapData objects (complex), dozens of times per second (frequent).

This raises an interesting issue. My Model object is unaware and independent of the View and Controller classes. But when the Model passes a reference to some of its data to the other classes, because that data is of type BitmapData, other classes can modify the data that's in the Model. I can prevent this by subclassing BitmapData and overriding its methods and properties, so that only an instance of my Model class can edit it. One could argue that my Model could simply pass a clone of the BitmapData object through the getter, but due to technical constraints I cannot expect that kind of code to run smoothly on most machines.

But is all this protection necessary? Is it the "responsibility" of the Model to prevent other classes from tampering with its data? If I give my Model instance to some other system, shouldn't I be bothered if the other system modifies the Model's data in this way?

Dazzer
August 10th, 2007, 12:04 PM
The point of the MVC, I think, is to abstract the View and the Model layers, through the use of the Controller interface. Its got absolutely nothing to do with whether other classes tamper with the model's data (although that should never happen). By abstracting those layers, you make them independent of each other. Less coupling is always a good thing.

For example, you have created a game based on the MVC pattern. Lets say you are making a tile based game, and for some odd reason you used a Dictionary object to store data about the map. The game works fine, and everything is good.

One fine day you realise the error of your ways. Its 1 week till release day. Do you need to rewrite everything all over again, making sure that your GUI accurately depicts the data in the model? No you don't, because you have abstracted the two layers via the controller.

Now, all you have to do is reimplement the features present in the old Model, and say, chuck in an Array instead. The Controller wouldn't even have a clue that something happened. It would just go along its merry way, as everything in its view works perfectly, even though the model has changed.

Rezmason
August 10th, 2007, 03:18 PM
I sort of agree. In MVC, only the Model class is truly abstracted. The View and Controller classes tend to be tightly knit together, because the Controller receives interface events from the View, so they both tend to be very concrete. The Model is unaware of the View and the Controller.

But all that's beside the point. I mean to focus on the Model's "permeability". A class's interface is meant to prevent its implementation from being exposed to outside classes. But if the interface passes an instance of the BitmapData class, doesn't that expose the class's implementation?

For instance:

public class A {
private var _n:Number = 5;
public function get n():Number {
return _n;
}
}
public class B {
private var _bd:BitmapData = new BitmapData(1,1, false);
public function get bd():Number {
return _bd;
}
}
var a:A = new A();
trace(a.n); // 5
a.n++;
trace(a.n); // 5

var b:B = new B();
trace(b.bd.getPixel(0,0)); // 0xFFFFFF
b.bd.setPixel(0, 0, 0xFF0000);
trace(b.bd.getPixel(0,0)); // 0xFF0000

Passing a complex data type allows code outside a class to alter data within it. So is this something that a programmer ought to prevent in his OOP?

Dazzer
August 10th, 2007, 09:04 PM
I would say yes, that is something you should do in the MVC pattern. Simply because you shouldn't be allowing the Controller to deal with complex data structures.

So your class B would implement methods such as "getPixel" as part of its interface.

The other method would be to pass a cloned bitmapData(). That way, even if they manipulate the data, they won't be changing the actual data in the structure.

Just my opinion. But I definitely see what you're getting at :)

Rezmason
August 11th, 2007, 02:28 AM
Quick note: I hit an interesting snag a few minutes ago. You cannot extend the BitmapData class, which isn't mentioned in the documentation. In most case, it's probably all for the better. The BitmapData class is the kind of class you would want to augment through composition, rather than inherit.

Sirisian
August 11th, 2007, 02:32 AM
You can extend the bitmap class I'd presume which would be a more logical choice. The bitmapdata class just holds data.

Rezmason
August 11th, 2007, 04:06 AM
You can extend the bitmap class I'd presume which would be a more logical choice. The bitmapdata class just holds data.

In this case, the point of extending BitmapData was to keep classes outside the Model from manipulating the data inside it. In an MVC design pattern, the Bitmap object, being a DisplayObject, would be in the View and (at least in this case) the BitmapData object, being data, would be in the Model. Getting the BitmapData from the Model to the View without letting the View edit the BitmapData was the challenge, because once you have a reference to a BitmapData instance, you can edit it.

The solution I found is for the Model to create a Shape instance with the dimensions of the BitmapData, and use the BitmapData as a bitmap fill to draw it to the shape. The shape is then passed to the View. Shapes, unlike Bitmaps, have no bitmapData property, so they can be used to draw BitmapData objects to the screen without any worries regarding unregulated access to Model data.

Dazzer
August 12th, 2007, 10:44 AM
Hmm... I don't like that solution either. I still think a cloned bitmapData object would be the way to go. Unless what the controller is expecting is a Shape, then that is fine. But the model should NOT be responsible for "drawing" the shape.

Rezmason
August 12th, 2007, 07:28 PM
In that case, I could have the View pass the Model a BitmapData object to draw on.

EDIT: It might be un-Model-like to have any method of the Model object involved in editing a BitmapData object, but due to the kind of data involved in this case, it makes more sense and will perform better to have a little "drawing" going on in the Model.