views:

94

answers:

4

I'm refactoring one of my projects - a shopping cart. One of the tightly coupled areas of my code is the "Viewer" class - to generate information for the user to see, it often needs a combination of two or more of the following objects:

  • The store catalog.
  • The customer's order.
  • The customer's mailing information.

I can't really break up the display methods, for various reasons.

Martin Fowler's Refactoring identifies this as a "Long parameter list" smell. The relevant refactoring here is "Introduce parameter object." I am, however, hesitant to do that, as doing so would couple loosely related data. It would also lock me to a very narrow one-to-one relationship between those three objects - while that would work for my application as it is now, it makes no real-world sense. (As there is only one store catalog, there can be many "Customer mailing information" objects, and each of those may be related to many "Customer's order" objects).

Does anyone have any elegant solutions to this?

+6  A: 

A parameter list of three parameters needs no refactoring. Start worrying when you reach, say, 8 or 10 parameters.

ammoQ
To clarify - I've got a good dozen methods that use a set or subset of those three objects - and the application is simple enough that it feels that there ought to be a more elegant solution.The application is by no means difficult to maintain, and I am performing this refactoring, for the sake of learning.
Vladislav
Beware of trying to make something "more elegant" when there is no actual problem on hand, as overengineering is the most likely result.
ammoQ
+1  A: 

As stated by ammoQ, looking for refactoring opportunities with so few parameters is stretching. See also: KISS and YAGNI.

Ryan Prior
+2  A: 

Try to name the thing that binds a catalog, an order, and an address. Start, maybe with CatalogOrderAddressTuple. Ugly, isn't it? Well, maybe as a utility class of your Viewer, it should just be an inner class, where you could get by with just Tuple - or Data. Still ugly.

It doesn't sound like these belong as actual fields to the Viewer - but explore what that would look like, how your code would change if each Viewer were simply constructed with the data on which it operates.

As ammoQ & Ryan Prior have said, this isn't much of a smell, but I'd say it's worth playing with some alternatives before giving up entirely.

Carl Manaster
After thinking about this problem some more, it seems that the root cause of this was in my failure to faithfully implement MVC - I should have probably specified that in my question. With a well-defined model class, I could just have the Viewer access Catalog/Order/MailingInfo through the Model, rather then have my Controller keep passing that data through it as parameters.
Vladislav
That sounds like a very good answer to me. Proper MVC rocks. I'm glad you stuck with it.
Carl Manaster
+1  A: 

It seems to me that introducing a parameter object would have the opposite effect of locking you to a one-to-one relationship between those three objects.

If a single customer address is being passed around, and in the future someone decides to separate billing address and shipping address, then it would probably be simpler to add the new address to a parameter object, rather than add a new parameter up and down the call stack.

(This is just an example, of course. Ideally, the address information would exist separately in the order and customer objects, since all information on posted orders should be immutable, even if the customer's address changes. But that wasn't what you were asking about!)

Jeffrey L Whitledge
That is true - I've made a pretty big blunder by going down that line of reasoning.
Vladislav