views:

228

answers:

5

I have method List<Foo> getFoos () which gets the data from remote server and returns it.

Of course, user shouldn't change number of items of the list because he'll get data not synchronized with data on the server (and if he want change number of items he has special methods like addFoo ()).

First approach was to return array and change method's signature to Foo[] getFoos (). But it's more common in java and more convenient to user to operate with collections so I changed signature to List<Foo> getFoos (). This method always returns

Collections.unmodifiableList (originalList)

So, when user try to change the list he will get RuntimeException.

Are there any recommendations about api design in similar cases?

+10  A: 

Collections.unmodifiableList if perfectly acceptable, and should be faster (no need to create an array).

Edit - In terms of API design, you should just make your javadoc clear ! People who use a method without reading its doc deserve the surprise :p

deubeulyou
I more care whether this confuse users and make them think that they can modify the list and all synchronization stuff will be done automatically (sync with server I mean).
Roman
Of course, after first RuntimeException all confused users will certainly understand that they can't do it so simply :)
Roman
@Roman In your documentation you just have to that an unmodifiable List is being returned.
Poindexter
Startling rather than accomodating programmers who assume your code is brittle and will tolerate side-effects, is for the betterment of software development, IMO.Also, if you are returning a collection of immutable objects, an alternative to returning a non-modifiable collection, is to return a modifiable collection that is distinct from the internal one maintained by your class. In other words, getFoo allocates and return a new collection with the same objects in it.
Noel Ang
A: 

If you want a custom, specialized property from an existing object, or List in this case why not try extending or contain it and make the relevant accessors to throw an exception?

The reason is because you may wish to allow some other client objects to modify the list; it depends on how close to the application level is the returned data.

Extrakun
I don't think extending List is a better approach than just using unmodifiableList. It is more work and it is very likely your own implementation is not as good as the one created by the Java devs.
Martin Sturm
I'd vote you up except for the fact that you mentioned extending in the same breath as containing. Containing is probably the best answer, extending would be the worst.
Bill K
+2  A: 

I'd also say it is perfectly acceptable and much better than returning an array (which some suggest should be treated as a deprecated type altogether). If you want to be more explicit about it in the API however, you could consider returning an ImmutableList from Google Collections.

Fabian Steeg
Yeah, the Immutable* collections are perfect for this sort of thing.
ColinD
I'm not sure that it can be called a good practice to use classes from 3rd-party libraries in API (even if it's written by google).
Roman
If that library hasn't made a public pledge of eternal backward-compatibility, akin to the JDK, you'd be right. In the case of Google Collections though, you're safe.
Kevin Bourrillion
+1  A: 

I virtually never return a naked list or array. If you have a collection of something, it nearly always has SOME code somewhere associated with it that should be a part of that collection. By not having a class around the collection you are forcing yourself to duplicate that code across different places where the collection is used.

There is also, generally, a variable or two that are associated with the collection. You'll find you pass them whenever you pass the collection. These belong in the business logic class that wraps the collection.

Bill K
A: 

If you have complete freedom and it seems you do, then you should not have to choose between array or List, rather return an iterator. This would also help if you need uniqueness so instead of returning Set - still return iterator.

Navi
Do you really think that obtaining an iterator is more convenient to the user than obtaining List or Set or Array?? (tip: what if he needs to iterate twice? what if he needs to get size? what if he needs to work with the whole collection rather than with concrete elements i.e. do operations like xxxAll() ...)
Roman