I’m making a calculator app to learn Objective-C and maybe improve my OO design skills a bit. In an attempt to do things more MVClike, i have separated the actual do-the-calculator-stuff code from the view controller. For every action, pretty much all the view controller does is tell the “model” to do the operation meant for that action.
Thing is, that gives me a bunch of methods that do basically nothing but forward the action to the model, like this:
- (IBAction)clearAll:(id)sender {
[self.model clearAll];
}
- (IBAction)clearDisplay:(id)sender {
[self.model clearDisplay];
}
- (IBAction)clearMemory:(id)sender {
[self.model clearMemory];
}
- (IBAction)storeMemory:(id)sender {
[self.model storeMemory];
}
- (IBAction)addMemory:(id)sender {
[self.model addMemory];
}
- (IBAction) subtractMemory:(id)sender {
[self.model subtractFromMemory];
}
- (IBAction)recallMemory:(id)sender {
[self.model recallMemory];
}
Objective-C so far seems outrageously flexible with dynamically forwarding messages, and these methods are alike enough to look rather easily automated away. Do they really have to be there? Or is there a less repetitive way to tell the controller to just pass certain messages through to the model (ideally, while stripping off the sender arg)?
I’ve been looking a bit and trying some stuff with selectors and NSInvocation, but it seems like that’d mess with Interface Builder by taking away all the (IBAction) markers that let me hook up buttons to actions. (I’d prefer if the view didn’t have to know or care that the controller’s just forwarding to the model in these cases.)
So, is there a less repetitive and/or hacky way? Or is it not worth the trouble? (Or is it a bad idea in the first place? Or is this trying to make the model do too much? Or…)
You can do what Gabriele suggested and it is certainly an example of how dynamic ObjC can be, but you are likely better off avoiding it. As Gabriele said, you’d better know exactly what you are doing and definitely not to overuse such feature. And that often indicates that such feature is likely more trouble than it is worth.
The reality is that your calculator application is a quite contrived for the purposes of driving home the separation inherent to the Model-View-Controller pattern. It is a learning app, as you state.
In reality, no application is ever that simple. You will rarely, if ever, have a field of buttons where that the control layer blindly forwards said functionality on to the model.
Instead, there will be all manners of business logic in that control layer that will may do everything from automating various actions to validation (potentially by querying the model) to updating UI state in response to various actions.
Likely this code will be present from very early in the project, thus that generic forwarding mechanism will quickly become completely unused.
As well, such forwarding mechanisms become funnels full of pain when it comes to debugging. you no longer have a concrete spot to drop a breakpoint, but now have to add conditions. Nor do you have an easy means of finding all the places that might invoke or implement a particular method. As well, it makes following the control flow more difficult.
If you do find yourself with lots of repetitive boiler-plate code, it is more of a sign that your architecture is likely flawed than a sign that you need to inject a spiffy dynamic mechanism to reduce the repetitiveness.
As well, if you were to continue to flesh out your calculator app, how much of your coding time would have been spent doing those repetitive methods vs. all other features in your app? Likely, very very little and, because of their simplicity and convenience to debugging, it is unlikely that said repetitive methods are ever going to incur any significant maintenance cost whereas a spiffy-dynamic bit of trickery (which is very cool and I encourage you to explore that in other contexts) is pretty much guaranteed to require a “Huh. What was I thinking here?!” moment later on.