How decoupled should controllers and views really be in MVC? - model-view-controller

Views are, by definition, supposed to be logicless. When a user interacts with a view, it notifies its controller. When state changes in the app, the controller notifies the view. But I'm confused as to the nature of the communication between view and its controller when it's time to re-render some or all of the view.
Let's pretend I'm making a two player card game. The view is responsible for showing the deck, the discard pile, the cards in players' hands, and any other UI components. When a player plays a card, the view needs to reflect this change, and it's the controller's job to notify the view to do so. Which of these options is the best way to handle this event?
The controller tells the view simply to re-draw. The view, through the controller, has access to all the parameters of the game state. It uses these parameters to re-draw everything including the deck, both player's hands, etc.
The controller tells the view that a player played a card. The view knows that when a player plays a card, only that player's hand needs to be re-drawn. Like option 1, the view uses the parameters of the game state to determine how to re-draw the player's hand.
(Similar but different from 2) The controller tells the view to re-draw that player's hand and passes it all the parameters needed to do so. The view has no access to game parameters.
Any other approach I'm missing?
Option 1 seems to be the easiest two write because the view is stateless -- it just re-draws everything every time. But for that same reason, it is very wasteful. We don't need to draw both player's hands when just one player played a card. It's also difficult to do things like animation because every time we re-draw, we're essentially throwing away our old canvas and building a fresh one with all new view components.
On the other end of the spectrum, option 3 seems to be best in terms of removing logic from a view, but it comes with some issues. First, I've found it more difficult to write because it's imperative that all the proper messages are sent to the view. If any are missed, the view won't properly reflect the state of the app. Second, it seems like a full re-draw is still necessary at times for when, say, the user is restoring a saved game in progress.
In both options 1 and 2, the view "pulls" data about the game state whereas this data is "pushed" to it in option 3. Should views be able to request information like this, or does this imply that there's too much logic in the view?
Thanks in advance for any light you can shed on this topic!

MVC is not the best fit for all applications. It also depends on what kind of frameworks which are available.
By not taking the platforms/frameworks into account I'll say that HMVC (Hierarchical model–view–controller) or PAC (Presentation–abstraction–control) is a better fit for you since a page can be splitted up into several parts (three views: hands & deck).
When it comes to native applications (GUI) it seems like MVP is preferred over MVC.
Martin Fowler has a nice article about the different GUI patterns here: http://www.martinfowler.com/eaaDev/uiArchs.html

Related

WebComponents-like objects (or nested controls) in Xcode

I created a custom NSView that displays some data exactly the way I want it to (a line chart of sorts). I now want to add a couple of sliders to have the ability to zoom the displayed data in and out. I would also like to add a couple of checkboxes so that the incoming data can be interpreted and graphed in different ways, and maybe some scrollbars to be able to see past data. I need to have at least 5 copies of this view (with all its controls) on screen at the same time, each showing a different data feed.
This way of thinking a user interface falls nicely into the WebComponents paradigm where you can design a component that encapsulates many different ones. As I understand it, there is no way of nesting controls like this into a master control in Xcode.
Of course I could layout all the views and all the controls separately inside a view controller and achieve exactly what I want but it would not be as maintainable as having ONE object that I can duplicate either in interface builder or in code.
My question is: what is the proper way to achieve this in Xcode (if any)? I don't need code examples but rather a conceptual answer and I'm only interested in answers related to Cocoa rather than CocoaTouch.
I just learned that you can have multiple view controllers as child controllers. This is exactly what I was looking for as it maximizes reusability and reduces maintenance.

The same UIView in two places at once?

In order to explain what problem I am having I will quickly explain the scenario. I have a synthesizer I am building that has several "control views". One control view may be 4 vertical sliders while another is one big matrix or something.. So, say I have control views 1-4. In addition, I have two main sections (which are just holder views), which can contain one of the 4 control views. At any given moment, sectionA can have controlView4 while sectionB can have controlView2. This works perfectly.
The problem with this is SectionA cannot have ControlView1 while SectionB has ControlView1 simultaneously. This leads to undesirable behavior. For example, if SectionA currently has ControlView1 while SectionB has ControlView4 (which will wrap around to ControlView1 on the next toggle), than the next time I toggle SectionB's active ControlView, SectionA's ControlView will simply disappear. (presumably because UIKit implicitly removes it from SectionA's subviews when I add it as a SectionB's subview.)
So, there is some default behavior of UIView that isn't ideal for this modular scheme I wish to implement. That being said, is there a way to achieve what I want without deviating to far afield from iOS best practices and sane code design?
First, I would want to have a different type of view controller for each type of view. Then, each time I wanted a view in a section, I would create its matching controller and have it take over that container area. If the four sections are then displaying multiple copies of the same view, they each have their own controller to keep them organized.
Assuming you have your data model separate from your views and controllers, there should be no extra complexity.

Hooking up multiple NSViewControllers to a nib

I have a window that contains several rather complex views. Right now, I'm using a single NSWindowController to control the UI for the window and all the views. It's becoming a pretty huge class, since it's dealing with the details of each and every view.
The view behaviors are independent from one another though, so I see an opportunity to put the UI logic for each view into a separate controller.
According to the Mac App Programming Guide, this is exactly what view controllers are for:
Use view controllers to divide up the work for managing more
sophisticated window layouts. Your view controllers work together
(with the window controller) to present the window contents.
However, I can't find any documentation or examples on how this idea works in practice. Can I add multiple view controllers to the nib file in addition to the window controller?
If you add the view controllers to the nib, that's where they're going to be instantiated, and you'd add IBOutlets to the window controller (assuming that's the nib's File's Owner) in order to connect them.
In terms of memory, however, that scheme could become expensive, especially the more view controllers you have. You may want to instead consider lazily instantiating them in the window controller, (i.e., doing so only when needed), assuming this doesn't result in an objectionable lag before the view is presented for the first time.
Don't be afraid to try both approaches. One of them may be best for you.
In any case, I applaud you for your decision to factor out all that code into separate controllers. Very nice. Good luck to you in your endeavors.

MVC design pattern in complex iPad app: is one fat controller acceptable?

I am building a complex iPad application; think of it as a scrapbook.
For the purpose of this question, let's consider a page with two images over it.
My main view displays my doc data rendered as a single UIImage; this because I need to do some global manipulation over them. This is my DisplayView.
When editing I need to instantiate an EditorView with my two images as subviews; this way I can interact with a single image, (rotate it, scale it, move it). When editing is triggered, I hide my DisplayView and show my EditorView.
In a iPhone app, I'd associate each main view (that is, a view filling the screen) to a view controller.
The problem is here there is just one view controller; I've considered passing the EditorView via a modal view controller, but it's not an option (there a complex layout with a mask covering everything and palettes over it; rebuilding it in the EditorView would create duplicate code).
Presently the EditorView incorporates some logic (loads data from the model, invokes some subviews for fine editing, saves data back to the model); EditorView subviews also incorporate some logic (I manipulate images and pass them back to the main EditorView). I feel this logic belongs more to a controller. On the other hand, I am not sure making my only view controller so fat a good idea.
What is the best, cocoa-ish implementation of such a class structure?
Feel free to ask for clarifications.
Cheers.
Huge fat controllers are fine.
If necessary, just break off some "purely logical parts" from it and shove them in other "helper classes". And use tricks like categories extensively where you can.
Definitely go with a HFC (huge fat controller) if that feels right.
Then, just get on your engineering bike and slim the hell out of it!
You should definitely not avoid the right structure, the good structure, the structure you want, just because one thing will be too big.
Just slim that big thing down by outsourcing concepts, going nuts with categories, etc etc - every trick in the book.
My belief!
Some reasons to wrap a viewcontroller around your view:
to use it in an Apple API that requires a viewcontroller (popover views, modal views, navigation bars, tab bars, ...)
because the view can be invisible for a while, and so it makes sense to clean it up in low memory situations. The viewcontroller then guards the data that needs to survive such an unload-reload cycle.
because you just like the MVC pattern
I think the second bullet justifies a viewcontroller for your editable content view and another one for your non-editable content view.

Simplifying a complicated Cocoa-Touch View Controller

As I wire up my first fairly complicated Cocoa-Touch view I feel like I'm inadvertently slipping back into old procedural patterns and finding it difficult to shake them off...Though fully aware of many of the Cocoa (OO) design patterns I'm afraid I may be subverting them.
As such this view in question is quickly becoming unmanageable and I'm wondering if I might be approaching it the wrong way?!? The view is managed by a subclass of UIViewController. The view itself contains ±10 subviews. Some of these subviews "slide" in and out and contain their own subviews (controls, imageviews, etc) that slide along with them.
Without getting into too much detail I've found that I'm executing most (if not all, including animation) of my management code w/in the touchesBegan/Moved/Ended methods of my root View Controller. And it's become a mess of managing, setting & checking boolean properties. if (editingMode & panelAVisible).... if (editingMode & panelBVisible)... or *if (viewFlipped) { for (MyCustomView view in someArrayOfSubviews)} etc, etc... granted the UI of this app requires most of these views (or their contents) to be touched and moved by the user to different parts of the screen.
The main problems I'm trying to solve seems to be along the lines of: if viewA is present then you 3 views go hide (animated)...or, If viewB is touched then all objects contained in viewC are negative... etc.
Any clever (or rudimentary) OO approach to handling this? Perhaps make the subviews that contain views act as their own mini view controllers? I haven't been able to find too many (any?) examples of that though...
As you suggested at the end of your question, I would recommend having a subcontroller whenever you need logic for a particular subview. The point of a controller object is to keep track of state of the view and to encapsulate all that view logic that you were describing. Interface actions, such as if the user can move to a different screen, can invoke save logic, can create a new document, should be in the controller for that particular view. This will help maintain a separation of concerns between the various controllers and cut your convoluted logic down at the top level.
While it doesn't pertain to iPhone programming specifically, the book Cocoa Programming for Mac OS X contains good examples (especially in the chapter about how to do preference windows) of using subcontrollers and subviews in your application.
I think you should go along your last suggestion, make the subviews that contain views act as their own mini view controllers. Each (sub)view that presents a 'screen full of content' could/should be managed by its own view controller.
Animating between those views can be done with the build in navigation controller (you can actually hide the top bar of a navigation controller) such that you have the default slide animation. Otherwise you could indeed create your own animation while still using that navigation controller.
'The view itself contains ±10 subviews'. Some of these subviews "slide" in and out [..]'. These subviews you're talking about are perfect candidates for extraction from your one monolithic UIView.
The basic OO principle to use is how the navigation controller does it, by pushing and popping views on and off a stack. Each view pushed and popped is handled by its own view controller.
HTH
Edit: I now see you're not specifically talking about iPhone development. Still, have a look how its done there (especially the UINavigationController). You can still get the basic design idea

Resources