What's an appropriate design pattern for this hierarchical class structure? - objective-c

I have a class that instantiates a hierarchy of classes. The interface should hide all of the internal hierarchy by presenting a single class reference. (An the interface to the classes at intermediate levels should hide internal implementation details the same way.) I am having a little difficulty deciding how to flow the interface parameters down to the lowest levels and to flow state changes up to the top level. What I have come up with gets messy.
I have seen some discussions of the blackboard pattern but, from what I have seen, it looks ad hoc and flat rather than hierarchical. (Although flat vs hierarchical may not be important.)
The class I have is a calendar view, subclasing UIView. The hierarchy includes a header class, a grid class (instantiated more than once), a tile class (instantiated many times), plus some helper classes. It's based on Keith Lazuka's kal calendar in Objective C. I've decided to reorganize it for my needs, and wanted to rethink this part of it before I introduce problems with flexibility.
My question is in the title.

I have decided that the KVO (Key Value Observer) design pattern makes sense for bubbling state information from the lower levels to the top. Only that state information that needs to flow up is observed at each of the corresponding layers.
In this application, a tapped tile event is sent to the observer at the next level up (the grid level), telling it that the user has selected a date, which is a property of the tile class.
At the grid level, it changes its state based on its current state and the new information that it's observer receives from the tile. (In my calendar, the user can select a range of dates by choosing start date and end date, and can continue tapping tiles to change his date range selection.) This changes state at the grid level translates into a change in the start and/or the end date, so an NSDictionary property is updated.
At the calendar level, an observer sees the startDate/endDate dictionary change. Regardless of which grid this came from (there are two grids, and only one of them is active at a time. The tiles and the calendar do not need to be aware of this) the calendar's start and end dates are updated.
The calendar is a view that is planted into one of the other views of the application, initialized with a month to be shown, and with a selected date range (start and stop dates). Information is flowed down from the top though the pointers to each of the immediate subviews at any layer. Those subviews take care of keeping their subviews configured. I have eliminate the need to add explicitly add delegate methods or callbacks, and that has simplified the connections from top to bottom. Connections only go the the immediate level above or below in the hierarchy.
This may not seem like much after all, because it looks rather straightforward. But it wasn't clear until I spent awhile thinking about it. I hope it gives others some ideas for their own code. I would still like to know if there are other suggestions responding to my question.

Related

OOP - is it better to pass big controller objects to children, or have children dispatch events?

I'm a fairly experienced programmer, but I've always struggled with this particular issue..
You have your main class that maybe displays pop-ups over everything else, transitions between screens and so forth, and then you have the screen objects themselves, and the pop-up objects. when you click "close" on a pop-up, or click "go to a new screen" on a screen, or whatever it may be, these objects then need to communicate with the main class and tell it to do stuff. And often you need to pass data to the main class aswell. In your experience does it work out better to have the children dispatch events with data, that the main class picks up, or somehow pass the main class down to all the children through constructors, and have a bunch of public methods in the main class that the children can call?
or are both equally valid?
edit: And also, what made me post this: In my game, the user goes through a bunch of different menu screens, and in each screen, he adds something to a game-config object that at the end will be used to generate the gameScreen. I dont want to keep saying dispatchEvent("addValueToGameConfig", value) or something, i just want to say bigController.gameConfig.value = "whatever";
If the hierarchy of children is deep, I would go for events or observer. It leads to a lower coupling between classes. Any substantial refactoring of your main class can have a huge avalanche effect on the dependent children. They become too knowledgeable (higher change of breaking Law of Demeter) about their parent and take on effectively an additional responsibility (arguably breaking SRP) besides managing their own state, of informing it constantly about their own state in a custom manner compatible with their parent. Firing a specialized meaningful notification about their state change into "space", not just about an arbitrary property change, releases them from worrying about the parent's state. It is a parent's duty now to be informed about changes of the state of its children. Furthermore, having a set of meaningful events can lead to narrower public interface of children. It may as well help readability, not having to constantly go up and down through the hierarchy.

Applying MVC philosophy in Objective C

I'm starting a small project that displays circles having random radii, random color and random position on the screen. I want to implement this using the MVC paradigm in Objective C.
I have a class Circle that contains the following instance variables:
CGFloat radius
CGPoint center
UIColor radiusColor
This class doesn't contain methods, it just holds data. It is put in a separate file. (Circle.m & Circle.h)
I have a myModel class that is supposed to be the model for my MVC. It contains methods that randomly generate centers inside bound of my view, where the bound dimensions are requested from the View throughout the controller.
Every time a random property (that is center, color and radius) is generated, an instance of the Circle class is created within the myModel class, and stored in an NSMutableArray.
When the generation is done, this NSMutableArray is passed to the controller, which in turn passes it to the view, thus displaying the circles.
My question is that if I am to implement the MVC paradigm correctly, should :
The Model (myModel) hold instances of Circle, or the instances of Circle should be held by the controller?
My model be made of 1 class, or is it legal to be made of several classes?
The model know the bound size of the view or is that something that a violation in the MVC philosophy?
One last question. If I have made the implementation as I have stated above, are myModel and Circle separate models or both classes constitute one model?
Thank you!
[Should] The Model (myModel) hold instances of Circle, or the
instances of Circle should be held by the controller?
The model should hold the data. That's it's job. Imagine what would happen if you wanted to change the interface to your program. Instead of (or in addition to) drawing circles on the screen, you might want to display a list of circles and their locations. You'd might want to change or replace the view controller to do that, but you wouldn't need to change the model that stores the circles. Likewise, you might want to change the way that circles are generated, but keep displaying them the way you are now. In that case, you'd change the model, but the view controller and view could probably stay the same.
[Should] My model be made of 1 class, or is it legal to be made of several classes?
A data model is typically a whole graph of objects, very often of different types. You might have one object that manages the rest (although you don't have to). For example, your MyModel class contains an array that stores Circle objects. You could add Square objects, Group objects, etc.
[Should] The model know the bound size of the view or is that
something that a violation in the MVC philosophy?
The model shouldn't know specifically about the view, but it's fine for the view controller to tell it to produce circles within a given range of coordinates. That way, if the view changes size or orientation, the view controller will likely know about it, and it can in turn give the model new info.
If you have other components to your model than just circles, wrap everything in myModel. Even if you don't, you might still want to do so to allow for future additions.
Depends on your design. If you are writing a "document based" application (regardless of whether you are using UIDocument) you normally would have a single class that contains the others. Even if you aren't, having a single root class for archiving purposes, etc., is usually convenient.
The model should definitely not know anything about the view hierarchy. (Note that this is different from knowing something like "canvas size" - it would be legitimate to store such a property in the model, and let the view display the canvas however it wishes, such as in a UIScrollView.)
Btw, kudos for thinking about this ahead of time!

Does setting the text of a simple text label go against MVC?

In MVC the View shouldn't hold it's data. However I know in Objective-c you do: [textField setString:#"hello"];, that string is then retained by the text field. The same applies for the textField's font and text colour, etc.
However a UITableView uses a datasource to ask a controller for it's data, it's then up to the controller to reload the table view. But it also stores some data itself, like background colour.
I can understand a reason as to why a UITextView doesn't use a data source the code would become much more lengthy, if every property had to be a method. But why use a data source in some cases and not others, why not just set an array of UITableViewCells (I know that this means cells could not be reused and so it would use more memory, but what other design reason is there), for the UITableView to display?
And when creating you own objects how do you know when to just store a small amount of generic data (e.g. the string a textview displays can only be a string, but any the string itself can be anything)in a view, or use a datasource?
MVC is a pattern, not an edict. Let the view do the work. Some coupling is just going to happen. Follow the guidelines of the pattern, and bend it to the style and desires of your developers and organization.
I'm not familiar with objective-c's mvc framework, but I think I understand the question.
Basically, you don't want the view doing anything with the datasource backend, that is, anything having to do with the plumbing of accessing the DB.
But its ok for the view to have access and use the data itself. That is the M part of MVC. The model gets passed around. The view knows how to display it. The controller knows how to do the business logic to it (including interacting with backend systems like the data access layer).
In the case of data grid, it has to hit the backend to get the data, so it has to rely on the controller.
Ideally, the view knows only about display related information (like the background color). The whole idea being separation of concerns. You want the view to handle just its part of things, like-wise the controller. Then you can modify them independently of each-other.
As for the specifics of the datasource (versus an array), grids tend to be complex. Maybe that is handling paging or other niceties. In this case, I don't think its so much the separation of layers (since an array could just as easily be the model), but handling more functionality.
I'm not sure what you mean re 'storing' small amounts of data in the view. The view should tend to deal with 'view stuff'.

How do I keep track of the data represented by a view?

I'm attempting to do a better job of keeping my data and my visual representation of data separate in a new project and I'm having some trouble with the abstraction.
I have a list of objects in a set that are part of an inventory and I use that data to generate some UIImageViews that get placed into the interface, thus keeping my models and views separate. When a user taps on the UIImageView, I want to be able to take an action on the data in the set as well as modifying the corresponding view.
How do I keep track of the object that is being represented by the UIImageView? I would think there's some sort of mechanism by which I can say "here's a reference to the object that you represent" but I can't figure out if that exists or if there's a more accepted way to achieve the view/model separation.
you could create and object that is an extension of the ImageView and upon initialization of that view, associate a property in the view to your data associated with the view.

How to keep model & controller separate from a CALayer based UI?

I'm trying to re-implement an old Reversi board game I wrote with a bit more of a snazzy UI. I've looked at Jens Alfke's GeekGameBoard code for inspiration, and CALayers looks like the way to go for implementing the UI.
However, there is no clean separation of model and view in the GeekGameBoard code; the model is the view, which makes it hard to, for example, make a copy of the game state in order to perform game-tree search for the AI player. However, I don't seem to be able to come up with an alternative way to structure that allows a separation of model and view that doesn't involve a constant battle to keep two parallel grids (on for the model, one for the view) in synch. This, of course, has its own problems.
How do I best best implement the relationship between an AI search-friendly model structure and a display-friendly view? Any suggestions / experiences would be appreciated. I'm dreading / half expecting an answer along the lines of "there is no good answer: deal with it as best you can" but I'm prepared to be surprised!
Thanks for the answer Peter. I'm not entirely sure I understand it fully, however. I can see how this works if you just have an initial set of pieces that are moved around, and even removed, but what happens when a person puts a new piece down? Would it work like this:
User clicks in the view.
View click is translated to a board location and controller is notified.
Controller creates a new Board with the successor state (if appropriate, i.e. it was a legal move).
The view picks up the new board via its bindings, tears down the existing view/layer hierarchy and replaces it with the current state.
Does that sound right?
PS: Sorry for failing to specify whether it was for the iPhone or Mac. I'm most interested in something that works for the iPhone, but if I can get it to work nicely on the Mac first I'm sure I can adapt the solution to work on the iPhone myself. (Or post a new question!)
In theory, it should be the same as for an NSView-based UI: Add a model property (or properties), expose it (or them) as bindings, then bind the view (layer) to the model through a controller.
For example, you might have a Board class with Pieces on it (each Piece having a reference to the Player who owns it), with all of those being model classes. Your controller would own a Board, and your view/layer would be able to display a Board, possibly with a subview/sublayer for each Piece.
You'd bind your board view/layer to the controller's board property, and in your view/layer's setter for that property, create a subview/sublayer for each piece, and bind it to any properties of the Piece that it will need. (Don't forget to unbind and remove all the subviews/sublayers when replacing the main view/layer's Board.)
When you want to move or modify a Piece, you'd do so using its own properties; these will translate to property accesses on the view/layer. Ostensibly, you'll have your layer's properties set up to animate changes (so that, for example, changing a Piece's position will cause the layer for it to move accordingly).
The same goes for the Board. You might let the user change one or both tile colors; you'll bind your color well(s) through your game controller to its Board object, and with the view/layer bound to the same property of the same Board, it'll pick up the change automatically.
Disclaimers: I've never used Core Animation for anything, and if you're asking about Cocoa Touch instead of Cocoa, the above solution won't work, since it depends on Cocoa Bindings.
I have an iPhone application where almost all of the interface is constructed using Core Animation CALayers, and I use a very similar pattern to what Peter describes. He's correct in that you want to treat your CALayers as if they were NSViews / UIViews and manage their logic through controllers and data via model objects.
In my case, I create a hierarchy of controller objects which also function as model objects (I may refactor to split out the model components). Each of the controller objects manages a CALayer, so there ends up being a parallel CALayer display hierarchy to the model-controller one. For my application, I need to perform calculations for equations constructed using this hierarchy, so I use the controllers to provide calculated values from the bottom of the tree up. The controllers also handle user editing events, such as the insertion of new suboperations or deletion of operation trees.
I've created a layer-hosting view class that allows the CALayer tree to respond to touch or mouse events (the source of which is now available within the Core Plot project). For your boardgame example, the CALayer pieces could take in the touch events, and have their controllers manage the back-end logic (determine a legal move, etc.). You should just be able to move pieces around and maintain the same controllers without tearing everything down on every move.