PDA

View Full Version : Alternatives to a switch statement?




GorillaPaws
Jun 14, 2012, 11:45 AM
I'm working on an iTunes style library app.

In my main window controller, I'll be receiving notifications when items are selected in the source list and updating the main content view by triggering the appropriate view controllers. The items being selected have properties defined as global constants that indicate their type. To use iTunes as an example, when you select music from the source list, the righthand view updates to load the music view, when you select the iTunes store, you get that view, etc.

I've read that using a switch statement to do different things based on what's passed in is a code smell, so I'm wondering what the alternative might be to something like:

int propertyType = [passedInObject valueForKey: propertyType];
switch( propertyType )
{
case kPropertyType0:
// Activate viewController for property type 0
break;
case kPropertyType1:
// Activate viewController for property type 1
break;
case kPropertyTypeN:
// Activate viewController for property type n... etc.
break;
}



chown33
Jun 14, 2012, 12:01 PM
I think it depends on exactly what is meant by "do different things".

In your case, you could have an array of view controller objects, and select one by index, where the index is the type. That's a certain kind of coupling, though, in that the type is presumed to be small positive consecutive integers. (And really, shouldn't the "type" be an enum, or even a typedef'ed enum?)

An alternative, if the type isn't consecutive integers, would be a dictionary where the key is the type (wrapped in NSNumber), and the value is the view controller. I would then make the propertyType be an NSNumber, not a primitive int or enum. Less wrapping and unwrapping that way.

Personally, I think the switch is fine. It's clear and concise, and has no dependency on another data object (array or dictionary). You can look at that switch statement by itself and determine its correctness.

I think the "code smell" is more for when there's a small integer argument and it's used to select between a multitude of unrelated actions or operations. As if a command-line had a single command "run" and "run 1" meant list the directory, "run 2" meant shutdown, and "run 3" meant recursive delete. The code smell is telling you that those are unrelated and opaque actions, each of which deserves its own uniquely named function.

So IMNSHO, I think the switch smells fine. If it were bigger or dynamic, then an alternative might be worthwhile. As it is, don't worry about it.

cMacSW
Jun 14, 2012, 12:06 PM
I don't think the case statement is a problem. Though if you're looking for a different way to do this, you could store the name of the view or view controller class as a string property in the object and create the view using these calls

Class theClass = NSClassFromString(classNameStr);
id myObject = [[theClass alloc] init];

GorillaPaws
Jun 14, 2012, 12:18 PM
Thanks for the reply chown33. I've actually implemented the types as enums, but I was just trying to simplify the example. Thanks for clarifying the "code smell" issue, your explanation is clear and very helpful (as always).

@cMacSW, thanks for the reassurance. Dynamically instantiating classes is another interesting idea. i guess for my current purposes, this wouldn't be necessary, but if we were in a situation where there could be a large number of these (or weren't defined at compile time), then this would be a really great approach. I'll be sure to keep this in mind for other situations.