Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I'm currently designing a protocol for internal use, so it doesn't make a huge difference in this particular case, but it got me wondering:

Is it better for a method to accept a single object of a specific type, or an array of objects, with the documentation specifying the type it will contain? Obviously the array allows for greater flexibility in calling the method, but specifying a type gives the programmer greater clarity as to what the method will be doing.

For example, my protocol has a single method (so far), called recieveDroppedItems:. It needs to accept either one or multiple NSURLs, which point at the files dropped on the sender.

Thanks in advance for any advice you have! :D

share

5 Answers 5

up vote 3 down vote accepted

There is no general answer to your question, but let me provide one to your example to point out some principles that generally apply.

Note: I shall henceforth speak of "interfaces" instead of "protocols", not only because it is arguably more common name for it in other languages, but also because I really mean interfaces in a more abstract way, as in "the definition of how something can be interfaced with".

When designing an interface, you should design it, as if you had no means to implement it yourself, but rather had to rely on somebody else, whom you will only be able to communicate your needs to through your definition.
If you assume this scenario, you see that you want an interface to be very clear (otherwise the implementation may not be designed to do what you expect) and very easy to implement (otherwise the implementation may fail to do what you expect).

Now in the context where you depend on the service abstracted to the interface you design, you should have been able to make several important decisions, that you shouldn't forward to the implementor to not force them to overstep the single responsibility principle, nor provoke code duplication. Instead, you need to make those decisions and convey them in your method invocation.
In this example, you might have:

  • figured out, whether some items can be processed in batch - assuming you expect any advantages in doing so
  • been able to filter out duplicates - assuming your system can produce any in the first place

And thus (under both assumptions) your contract with the implementor should be "you must be able to process a batch of unique URLs".

You can hardly transport this contract unambiguously without documentation, but you can try, for example by method names. IMHO receiveDroppedItems is not very expressive, because item is really ambiguous and receive also is in a language based on message passing.
I would call it processDroppedURLs. It's not longer, but it really says what's expected to happen. If I am asked to implement such a method, I think "Oh, ok, so I am expected to process a collection of dropped URLs" (assuming I know what dropped means in that context, I know all I need). Even though the collection's type might be defined to something as vague as NSFastEnumeration, I would expect for...in to yield NSURLs. As for the uniqueness information, I would probably rather put that into the documentation, rather than the method name, because it's not that vital.

So to summarize: You want clean, concise, almost minimalistic interfaces with expressive method names, that create abstraction barriers between the current client scope and the abstracted service scope, which are clear and simple from both sides.

share
    
Thanks for a very in-depth answer! Renaming the method to be more descriptive is a great idea. –  vilhalmer May 3 '11 at 16:25
    
+1: Careful naming (and renaming) is a great way to keep code both readable and maintainable. I would pick a good name over a good comment any time. –  molbdnilo May 11 '11 at 13:39

It depends on the overhead of sending a message, and how much you can simplify by handling only one notification at a time.

If you have high overhead (e.g., network protocol) and it's fairly easy to handle multiple notifications (which could certainly be the case in sending multiple URLs at once) then you might as well as allow multiples.

If you have low overhead (e.g., these are messages exchanged inside a single machine) there's a lot less motivation to coalesce messages.

share

Hate to tell you, but It Depends.

One case I've seen in common use is the J2EE HttpServletRequest.getParameterList(). It returns a Map<String, String[]>. Reason being, certain HTML form elements, like select boxes, can have multiple values. Or, there are multiple elements with the same name but different values (probably bad programming, but there are valid cases). In this case, the API designers decided that mutiple values were common enough to warrant forcing the array on all calls.

Look at the most common ways your API will be called. If you are getting multiple values a lot of the time, it's probably worth doing. Another option could be having two methods - one for a single value, and one for multiple.

share

The method could take a variable-length list of arguments; then it can accept just one, or more than on object (without the need to create an array to hold them).

share
    
This would be great, except I'm relying on performSelector: to call the method, and it only accepts a max of two arbitrary arguments. Although, I suppose I could use NSInvocation... –  vilhalmer May 3 '11 at 12:14

Depends on what language you're using because some languages won't allow heterogeneous arrays so unless your functions only accepts lists of strings or lists of other things or you enjoy casting all over the place your only option is to specify some product type and use that as input. Plus, in general, explicit types for inputs and outputs is better practice.

share
3  
This is tagged objective-c –  Phil Lello May 2 '11 at 17:17
    
@Phil Lello: Instead of an empty comment about a tag you should probably mention what makes objective-c so special that it applies to my answer. –  davidk01 May 2 '11 at 17:18
3  
@davidk01: If you're going to answer a language-specific question with a language-generic answer, it might be good to first research the language specified to see if your answer applies to it. –  FrustratedWithFormsDesigner May 2 '11 at 17:20
1  
@davidk01: No, you won't get the full answer from me because I don't know Objective-C well enough to answer. I will say your general-case advice was fine, but I think the OP was looking for something more specific to Objective-C and the OSX libraries that it looks like they're using. You're answer isn't "wrong", so now downvote, but I don't think it answers the OP as directly as they want, nor as directly as I would expect a subject-expert would answer. –  FrustratedWithFormsDesigner May 2 '11 at 17:30
1  
To specifically answer the question re: Objective-C, Objective-C is dynamically typed, so it does allow heterogeneous lists. (That said, the OP does specify that it only needs to accept objects of type NSURL.) –  mipadi May 2 '11 at 18:11

This site is currently not accepting new answers.

Not the answer you're looking for? Browse other questions tagged .