HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Code review of forward invocation

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
codeforwardreviewinvocation

Problem

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.

-
Expose a gridView property and do something like

[self.gameBoard.gridView doStuff];


-
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 sec

Solution

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.

Context

StackExchange Code Review Q#20749, answer score: 4

Revisions (0)

No revisions yet.