Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

Here's the situation. I'm writing a simple game and I had two main actors: GameController and GridView.

  • GridView is a UIView subclass displaying a grid with which the user interacts. It defines its custom delegate protocol (GridViewDelegate) for handling callbacks such as gridView:didSelectTile and others.

  • GameController is the game controller (duh!) which instantiate a GridView and set itself as a delegate, therefore implementing the GridViewDelegate protocol.

So far so good, then I decided to add HUD components on top of the grid (a score, a timer and other stuff). The most reasonable choice seemed to wrap such HUD components along with the grid into a new UIView subclass called GameBoard.

And here comes the design issue: I need the controller to talk to the GridView and I think there's two reasonable options here.

  1. Expose a gridView property and do something like

    [self.gameBoard.gridView doStuff];
    
  2. Forward the invocation made to GameBoard directly to GridView overriding the forwardInvocation: method of GameBoard

The first options looks like the most convenient, but I cannot get myself into liking it, due to the Law of Demeter.

So I decided to go for the second approach and do something like

// The GameBoard serves a proxy between the GameContoller and the GridView
- (void)forwardInvocation:(NSInvocation *)anInvocation {
    if ([self.gridView respondsToSelector:anInvocation.selector]) {
        [anInvocation invokeWithTarget:self.gridView];
    } else {
        [super forwardInvocation:anInvocation];
    }
}

// This method is necessary for the above forwardInvocation to work
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    NSMethodSignature * signature = [super methodSignatureForSelector:aSelector];
    if (!signature) {
        signature = [self.gridView methodSignatureForSelector:aSelector];
    }
    return signature;
}

It works as expected, but I'd like to have a second opinion on my design choice.

I generally tend to avoid overusing of the dynamic features of Objective-C, but it looked like an elegant way to achieve my result fulfilling the Law of Demeter.

share|improve this question
add comment

1 Answer

up vote 3 down vote accepted

I think you trying to overengineer solution a bit. First of all View should not do any stuff at all. View is just a View, sheet of paper. Maximum of view's responsibility is layouting himself. So controller should take care of other view-related stuff.

In this case I probably prefer to think about gridView as legitimate subview of GameBoard. I really doubt Demetra suffering when you doing something like [self.view.titleLabel sizeToFit].

So my advice is to use [self.gameBoard.gridView doStuff]; as simplest and straightforward solution.

share|improve this answer
    
By the way forwardInvocation will not be typechecked at all. Typesystem of Objective-C already too weak, don't make your life even harder. If you insist—I can advice to define @protocol for GameBoard with methods of GridView. –  Sёmka Novikov Jan 23 '13 at 4:09
add comment

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.