WindowsAzure/azure-sdk-for-java — pull request #55 by christophercurrie (2012-04-18 20:53:11+00:00)
Title: CloudTableClient should use Iterator instead of Iterable.

# The Problem

`CloudTableClient#execute(TableQuery, ..)` overloads return `Iterable`, which implies a collection that can be iterated over multiple times. However, the return value is implemented as an `Iterator` that implements `Iterable` by returning `this`, which is generally regarded as a Bad Thing. [More on this.] [1]

The temptation to do this is common given the seductive lure of being able to use your iterator in a foreach loop:

```java
foreach (Result r : tableClient.execute(query, resolver)) {
// handle results
}
```

But, because `execute` returns an `Iterator` under the hood, this breaks down if you try to do it twice:

```java
Iterable result = tableClient.execute(query, resolver);

foreach (Result r : result) {
// handle results
}

foreach (Result r : result) {
// never reached
}
```

`Iterable` expects this to work, as does mountains of client code that consume `Iterable` instances. The fact that `Iterator` can't normally be used in this way is a warning and reminder to users that iterators are single pass only.

*In general, methods that return a result that can only be iterated once should return `Iterator`, not `Iterable`.* This pull request implements that policy for `CloudTableClient`, at the cost of breaking client code.

# Alternative solutions

If breaking client code is not an option, the following alternatives can be explored:

## Deprecate the old code, and add new methods

This option keeps the broken old behavior but deprecates it, so that end user expectations aren't changed. New methods that return `Iterator` could be added to indicate the single-pass semantics.

## Keep the old interface, but make it support the correct semantics.

`Iterable` should return a new iterator for each call to `iterator`. There are some options for how to achieve this, such as (a) caching the results, or (b) issuing a new query to the service. Each choice has trade-offs, which is why dropping or deprecating the API should be preferred. But a correctly functioning API that has trade-offs is better than an incorrect one.

[1]: http://stackoverflow.com/a/5836220/9700