tags:

views:

78

answers:

3

When defining a customer-accessible API, what is the preferred industry practice between the following:

a) Defining a set of explicit API methods, each with a very narrow and specific purpose, for example:

SetUserName    <name>
SetUserAge     <age>
SetUserAddress <address>

b) Defining a set of more generalised parameter-based API methods, for example:

SetUserAttribute <attribute>

enum attribute {
    name,
    age,
    address
}

My opinion:

In favour of (a)

For boolean-based methods (e.g. EnableFoo) I would definely favour option (a) as the intentions are much more clear, it's less likely to require extensions in the future, and it makes more readable code.

For example, a method called EnableDisableFoo which takes a boolean parameter indicating whether to enable or disable would not be very clear, nor have a cohesive purpose.

It's where there are multiple options that the problem gets more complicated.

In favour of (b)

Option (b) is a great way of providing extensibility in the API, but at the expense of usability. With option (a), the API method name itself gives enough information to indicate what it is doing. With option (b), the user has to look up both the method name and the appropriate enumeration/parameter to use. In theory this makes option (b) worse from a usability standpoint -- but maybe having less methods is a good thing, so even this isn't completely true.

Other thoughts

It's necessary to strike a good balance between usability and extensibility, and they are often at odds with each other. But I'd like to think there is a more objective way to analyse this, rather than relying on the opinion of the API designer.

Does anyone have any thoughts on this?

+2  A: 

I would personally argue for (a), since our goal is to make the "static" code as accurate and reliable as possible.

By using the generalized form, we are introducing a risk for runtime errors. For example, I could set an attribute of type age with a value that is actually a string, etc.

This is very similar to the argument for defining and using enums or explicit types rather than using and returning ints in the old C style, as you get one more level of assurance.

While I agree that (b) allows extensibility, I have not seen too many APIs that would require this sort of extensibility for completely different types of attributes. The only common use of (b) is in polymorphic code, where the function could technically accept anything, including extensions.

Uri
+1  A: 

Another consideration is whether you want to set all attributes, and to set them simultaneously. For example, when you want to send something to a printer there may be dozens of parameters to be set (landscape or portrait; number of copies; page size; resolution; etc.). Instead of defining an API which needs to be invoked dozens of times, you can define a single function, which takes a struct as a parameter, where the struct contains dozens of fields, and where the caller initializes the struct at its leisure, and and then passes the struct in to the API in a single function call.

ChrisW
A: 

I think it depends on the code that you're writing. If you're writing about stuff that always goes together (i.e., if you're going to use/change age always with name), then go for b, otherwise a is fine.

But don't try to over-do (a) because then you're just going to write a lot more lines and get a lot less done. Good idea if you're paid for the amount of code you write though :)

Cyril Gupta